1.. SPDX-License-Identifier: GPL-2.0 2 3Aplicando Patches ao Kernel Linux 4+++++++++++++++++++++++++++++++++ 5 6Autor Original: 7 Jesper Juhl, Agosto de 2005 8 9.. note:: 10 11 Este documento está obsoleto. Na maioria dos casos, em vez de usar ``patch`` 12 manualmente, você quase certamente desejará considerar o uso do Git. 13 14Uma pergunta feita com frequência na Linux Kernel Mailing List é como aplicar 15an patch ao kernel ou, mais especificamente, a qual kernel base um patch para 16uma das muitas árvores/branches deve ser aplicado. Esperamos que este documento 17explique isso a você. 18 19Além de explicar como aplicar e reverter patches, uma breve descrição das 20diferentes árvores do kernel (e exemplos de como aplicar seus patches 21específicos) também é fornecida. 22 23 24O que é um Patch? 25================= 26 27Um patch é um pequeno documento de texto que contém uma diferença (delta) de 28alterações entre duas versões diferentes de uma árvore de código-fonte. Os 29patches são criados com o programa ``diff``. 30 31Para aplicar um patch corretamente, você precisa saber de qual base ele foi 32gerado e em qual nova versão o patch transformará a árvore de código-fonte. 33Ambas as informações devem estar presentes nos metadados do arquivo de patch 34ou ser possíveis de deduzir a partir do nome do arquivo. 35 36 37Como eu aplico ou reverto um patch? 38=================================== 39 40Você aplica um patch com o programa ``patch``. O programa patch lê um arquivo 41de diff (ou patch) e faz as alterações descritas nele na árvore de 42código-fonte. 43 44Os patches para o kernel Linux são gerados relativamente ao diretório pai que 45contém o diretório do código-fonte do kernel. 46 47Isso significa que os caminhos para os arquivos dentro do arquivo de patch 48contêm o nome dos diretórios do código-fonte do kernel contra os quais ele foi 49gerado (ou alguns outros nomes de diretório como "a/" e "b/"). 50 51Como é improvável que isso corresponda ao nome do diretório do código-fonte do 52kernel na sua máquina local (mas frequentemente é uma informação útil para ver 53contra qual versão um patch sem identificação foi gerado), você deve entrar no 54seu diretório de código-fonte do kernel e, em seguida, remover o primeiro 55elemento do caminho dos nomes de arquivos no arquivo de patch ao aplicá-lo (o 56argumento ``-p1`` para o ``patch`` faz isso). 57 58Para reverter um patch aplicado anteriormente, use o argumento -R para o patch. 59Portanto, se você aplicou um patch desta forma:: 60 61 patch -p1 < ../patch-x.y.z 62 63Você pode revertê-lo (desfazê-lo) assim:: 64 65 patch -R -p1 < ../patch-x.y.z 66 67 68Como eu passo um arquivo de patch/diff para o ``patch``? 69======================================================== 70 71Isso (como de costume no Linux e em outros sistemas operacionais do tipo UNIX) 72pode ser feito de várias maneiras diferentes. 73 74Em todos os exemplos abaixo, eu passo o arquivo (em formato não compactado) para 75o patch via stdin usando a seguinte sintaxe:: 76 77 patch -p1 < path/to/patch-x.y.z 78 79Se você quer apenas ser capaz de seguir os exemplos abaixo e não deseja 80conhecer mais do que uma maneira de usar o patch, então você pode parar a 81leitura desta seção aqui. 82 83O patch também pode receber o nome do arquivo a ser usado através do argumento 84-i, desta forma:: 85 86 patch -p1 -i path/to/patch-x.y.z 87 88Se o seu arquivo de patch estiver compactado com gzip ou xz e você não quiser 89descompactá-lo antes de aplicá-lo, você pode passá-lo para o patch desta outra 90forma:: 91 92 xzcat path/to/patch-x.y.z.xz | patch -p1 93 bzcat path/to/patch-x.y.z.gz | patch -p1 94 95Se você deseja descompactar o arquivo de patch manualmente primeiro antes de 96aplicá-lo (o que presumo que você tenha feito nos exemplos abaixo), basta 97executar gunzip ou xz no arquivo -- desta forma:: 98 99 gunzip patch-x.y.z.gz 100 xz -d patch-x.y.z.xz 101 102O que deixará você com um arquivo patch-x.y.z em texto puro que você pode 103passar para o patch via stdin ou pelo argumento ``-i``, conforme sua preferência. 104 105Alguns outros argumentos úteis para o patch são ``-s``, que faz com que o patch 106seja silencioso (exceto por erros), o que é bom para evitar que erros sumam da 107tela rolando rápido demais; e ``--dry-run``, que faz com que o patch apenas 108imprima uma lista do que aconteceria, mas sem realizar nenhuma alteração de 109fato. Por fim, ``--verbose`` diz ao patch para imprimir mais informações sobre o 110trabalho que está sendo realizado. 111 112 113Erros comuns ao aplicar patches 114=============================== 115 116Quando o patch aplica um arquivo de patch, ele tenta verificar a integridade do 117arquivo de diferentes maneiras. 118 119Verificar se o arquivo parece um arquivo de patch válido e checar se o código ao 120redor dos trechos sendo modificados corresponde ao contexto fornecido no patch 121são apenas duas das verificações básicas de integridade que o patch faz. 122 123Se o patch encontrar algo que não pareça totalmente correto, ele tem duas 124opções. Ele pode se recusar a aplicar as alterações e abortar, ou pode tentar 125encontrar uma maneira de fazer o patch ser aplicado com algumas pequenas 126alterações. 127 128Um exemplo de algo que não está "totalmente correto" e que o patch tentará 129corrigir é se todo o contexto coincidir, as linhas sendo alteradas coincidirem, 130mas os números das linhas forem diferentes. Isso pode acontecer, por exemplo, se 131o patch fizer uma alteração no meio do arquivo, mas, por algum motivo, algumas 132linhas tiverem sido adicionadas ou removidas perto do início do arquivo. Nesse 133caso, tudo parece correto, apenas mudou um pouco para cima ou para baixo, e o 134patch geralmente ajustará os números das linhas e aplicará o patch. 135 136Sempre que o patch aplicar um patch que ele teve de modificar um pouco para 137fazer caber, ele avisará você dizendo que o patch foi aplicado com **fuzz**. 138Você deve ser cauteloso com tais alterações porque, embora o patch 139provavelmente tenha acertado, ele nem /sempre/ acerta, e o resultado às vezes 140será incorreto. 141 142Quando o patch encontra uma alteração que não consegue corrigir com fuzz, ele a 143rejeita imediatamente e deixa um arquivo com a extensão ``.rej`` (um arquivo de 144rejeição). Você pode ler esse arquivo para ver exatamente qual alteração não 145pôde ser aplicada, para que possa corrigi-la manualmente, se desejar. 146 147Se você não tem nenhum patch de terceiros aplicado ao seu código-fonte do 148kernel, mas apenas patches do kernel.org, e você aplica os patches na ordem 149correta, e não fez nenhuma modificação por conta própria nos arquivos de 150origem, então você nunca deveria ver uma mensagem de fuzz ou de rejeição (reject) 151do patch. Se você ainda assim vir tais mensagens, então há um alto risco de que 152sua árvore de código-fonte local ou o arquivo de patch estejam corrompidos de 153alguma forma. Nesse caso, você provavelmente deveria tentar baixar o patch 154novamente e, se as coisas ainda não estiverem certas, aconselha-se começar com 155uma árvore limpa baixada na íntegra do kernel.org. 156 157Vamos examinar um pouco mais algumas das mensagens que o patch pode produzir. 158 159Se o patch parar e apresentar um prompt ``File to patch:``, então o patch não 160conseguiu encontrar um arquivo para ser modificado. O mais provável é que você 161tenha esquecido de especificar -p1 ou esteja no diretório errado. Com menos 162frequência, você encontrará patches que precisam ser aplicados com ``-p0`` em 163vez de ``-p1`` (a leitura do arquivo de patch deve revelar se este é o caso -- se 164for, isso é um erro da pessoa que criou o patch, mas não é fatal). 165 166Se você receber ``Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines).`` ou 167uma mensagem semelhante a essa, significa que o patch teve que ajustar o local 168da alteração (neste exemplo, ele precisou se mover 7 linhas de onde esperava 169fazer a alteração para fazê-la caber). 170 171O arquivo resultante pode ou não estar correto, dependendo do motivo pelo qual o 172arquivo estava diferente do esperado. 173 174Isso geralmente acontece se você tentar aplicar un patch que foi gerado contra uma 175versão de kernel diferente daquela que você está tentando modificar. 176 177Se você receber uma mensagem como ``Hunk #3 FAILED at 2387.``, significa que o 178patch não pôde ser aplicado corretamente e o programa patch não foi capaz de 179encontrar um caminho usando o fuzz. Isso gerará um arquivo ``.rej`` com a 180alteração que fez o patch falhar e também um arquivo ``.orig`` mostrando o 181conteúdo original que não pôde ser alterado. 182 183Se você receber ``Reversed (or previously applied) patch detected! Assume -R? [n]`` 184então o patch detectou que a alteração contida no patch parece já ter sido feita. 185 186Se você realmente aplicou este patch anteriormente e apenas o reaplicou por erro, 187basta dizer [n]ão (n) e abortar este patch. Se você aplicou este patch 188anteriormente e realmente pretendia revertê-lo, mas esqueceu de especificar -R, 189você pode dizer [**y**]es (sim) aqui para fazer o patch revertê-lo para você. 190 191Isso também pode acontecer se o criador do patch inverteu os diretórios de 192origem e destino ao criar o patch e, nesse caso, reverter o patch irá, na 193verdade, aplicá-lo. 194 195Uma mensagem semelhante a ``patch: **** unexpected end of file in patch`` ou 196``patch unexpectedly ends in middle of line`` significa que o patch não conseguiu 197fazer sentido do arquivo que você passou para ele. Ou o seu download está 198quebrado, ou você tentou passar para o patch um arquivo de patch compactado sem 199descompactá-lo primeiro, ou o arquivo de patch que você está usando foi alterado 200por um cliente de e-mail ou agente de transferência de e-mail em algum lugar pelo 201caminho, por exemplo, dividindo uma linha longa em duas linhas. Frequentemente, 202esses avisos podem ser corrigidos facilmente juntando (concatenando) as duas 203linhas que foram divididas. 204 205Como já mencionei acima, esses erros nunca deveriam acontecer se você aplicar um 206patch do kernel.org na versão correta de uma árvore de código-fonte não 207modificada. Portanto, se você obtiver esses erros com patches do kernel.org, 208você provavelmente deve assumir que o seu arquivo de patch ou a sua árvore está 209quebrada, e eu o aconselharia a recomeçar com um download limpo de uma árvore 210completa do kernel e do patch que deseja aplicar. 211 212Existem alternativas ao ``patch``? 213================================== 214 215Sim, existem alternativas. 216 217Você pode usar o programa ``interdiff`` (http://cyberelk.net/tim/patchutils/) para 218gerar um patch que represente as diferenças entre dois patches e, em seguida, 219aplicar o resultado. 220 221Isso permitirá que você passe de algo como 5.7.2 para 5.7.3 em um único 222passo. A flag -z do interdiff permite até mesmo passar patches em formato 223compactado com gzip ou bzip2 diretamente, sem o uso de zcat, bzcat ou 224descompactação manual. 225 226Aqui está como você passaria de 5.7.2 para 5.7.3 em um único passo:: 227 228 interdiff -z ../patch-5.7.2.gz ../patch-5.7.3.gz | patch -p1 229 230Embora o interdiff possa economizar um ou dois passos, geralmente recomenda-se 231realizar os passos adicionais, já que o interdiff pode errar em alguns casos. 232 233Outra alternativa é o ``ketchup``, que é um script em python para download e 234aplicação automática de patches (https://www.selenic.com/ketchup/). 235 236Outras ferramentas úteis são o diffstat, que mostra um resumo das alterações 237feitas por um patch; o lsdiff, que exibe uma lista curta dos arquivos afetados 238em um arquivo de patch, junto com (opcionalmente) os números das linhas de 239início de cada patch; e o grepdiff, que exibe uma lista dos arquivos modificados 240por um patch onde o patch contém uma determinada expressão regular. 241 242 243Onde posso baixar os patches? 244============================= 245 246Os patches estão disponíveis em https://kernel.org/ 247Os patches mais recentes estão vinculados na página principal, mas eles também 248possuem locais específicos. 249 250Os patches 5.x.y (-stable) e 5.x residem em 251 252 https://www.kernel.org/pub/linux/kernel/v5.x/ 253 254Os patches incrementais 5.x.y residem em 255 256 https://www.kernel.org/pub/linux/kernel/v5.x/incr/ 257 258Os patches -rc não são armazenados no servidor web, mas são gerados sob 259demanda a partir de tags do git, tais como 260 261 https://git.kernel.org/torvalds/p/v5.1-rc1/v5.0 262 263Os patches estáveis -rc residem em 264 265 https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/ 266 267 268Os kernels 5.x 269============== 270 271Estes são os lançamentos estáveis base publicados por Linus. O lançamento com o 272número mais alto é o mais recente. 273 274Se regressões ou outras falhas graves forem encontradas, um patch de correção 275-stable será lançado (veja abaixo) sobre esta base. Assim que um novo kernel 276base 5.x é lançado, um patch é disponibilizado contendo o delta entre o kernel 2775.x anterior e o novo. 278 279Para aplicar um patch mudando da versão 5.6 para a 5.7, você faria o seguinte 280(note que tais patches **NÃO** se aplicam sobre kernels 5.x.y, mas sim sobre o 281kernel base 5.x -- se você precisar mudar de 5.x.y para 5.x+1, você deve 282primeiro reverter o patch do 5.x.y). 283 284Aqui estão alguns exemplos:: 285 286 # mudando de 5.6 para 5.7 287 288 $ cd ~/linux-5.6 # muda para o dir do fonte do kernel 289 $ patch -p1 < ../patch-5.7 # aplica o patch do 5.7 290 $ cd .. 291 $ mv linux-5.6 linux-5.7 # renomeia o dir do fonte 292 293 # mudando de 5.6.1 para 5.7 294 295 $ cd ~/linux-5.6.1 # muda para o dir do fonte do kernel 296 $ patch -p1 -R < ../patch-5.6.1 # reverte o patch do 5.6.1 297 # o dir do fonte agora é o 5.6 298 $ patch -p1 < ../patch-5.7 # aplica o novo patch do 5.7 299 $ cd .. 300 $ mv linux-5.6.1 linux-5.7 # renomeia o dir do fonte 301 302Os kernels 5.x.y 303================ 304 305Kernels com versões de 3 dígitos são kernels -stable (estáveis). Eles contêm 306correções críticas relativamente pequenas para problemas de segurança ou 307regressões significativas descobertas em um determinado kernel 5.x. 308 309Esta é a ramificação recomendada para usuários que desejam o kernel estável mais 310recente e não estão interessados em ajudar a testar versões de desenvolvimento 311ou experimentais. 312 313Se nenhum kernel 5.x.y estiver disponível, então o kernel 5.x com o número mais 314alto será o atual kernel estável. 315 316A equipe -stable fornece patches normais, bem como incrementais. Abaixo está 317como aplicar esses patches. 318 319Patches normais 320~~~~~~~~~~~~~~~ 321 322Estes patches não são incrementais, o que significa que, por exemplo, o patch 3235.7.3 não se aplica sobre o código-fonte do kernel 5.7.2, mas sim sobre o 324código-fonte do kernel base 5.7. 325 326Portanto, para aplicar o patch 5.7.3 ao seu código-fonte existente do kernel 3275.7.2, você deve primeiro remover o patch 5.7.2 (de modo que reste apenas o 328código-fonte do kernel base 5.7) e então aplicar o novo patch 5.7.3. 329 330Aqui está um pequeno exemplo:: 331 332 $ cd ~/linux-5.7.2 # muda para o dir do fonte do kernel 333 $ patch -p1 -R < ../patch-5.7.2 # reverte o patch do 5.7.2 334 $ patch -p1 < ../patch-5.7.3 # aplica o novo patch do 5.7.3 335 $ cd .. 336 $ mv linux-5.7.2 linux-5.7.3 # renomeia o dir do fonte do kernel 337 338Patches incrementais 339~~~~~~~~~~~~~~~~~~~~ 340 341Os patches incrementais são diferentes: em vez de serem aplicados sobre o kernel 342base 5.x, eles são aplicados sobre o kernel estável anterior (5.x.y-1). 343 344Aqui está o exemplo para aplicar estes:: 345 346 $ cd ~/linux-5.7.2 # muda para o dir do fonte do kernel 347 $ patch -p1 < ../patch-5.7.2-3 # aplica o novo patch do 5.7.3 348 $ cd .. 349 $ mv linux-5.7.2 linux-5.7.3 # renomeia o dir do fonte do kernel 350 351 352Os kernels -rc 353============== 354 355Estes são os kernels candidatos a lançamento (release-candidate). São kernels 356de desenvolvimento publicados por Linus sempre que ele considera que a árvore 357atual do git (a ferramenta de gerenciamento de código-fonte do kernel) está em 358um estado razoavelmente íntegro e adequado para testes. 359 360Estes kernels não são estáveis e você deve esperar quebras ocasionais se pretender 361executá-los. Esta é, no entanto, a mais estável das principais ramificações de 362desenvolvimento e é também o que eventualmente se tornará o próximo kernel 363estável, por isso é importante que seja testado pelo maior número possível de 364pessoas. 365 366Esta é uma boa ramificação para pessoas que querem ajudar a testar kernels de 367desenvolvimento, mas não querem executar algumas das coisas realmente 368experimentais (essas pessoas devem ver as seções sobre os kernels -next e -mm 369abaixo). 370 371Os patches -rc não são incrementais; eles se aplicam a um kernel base 5.x, assim 372como os patches 5.x.y descritos acima. A versão do kernel antes do sufixo -rcN 373indica a versão do kernel na qual este kernel -rc eventualmente se tornará. 374 375Portanto, 5.8-rc5 significa que este é o quinto candidato a lançamento para o 376kernel 5.8 e o patch deve ser aplicado sobre o código-fonte do kernel 5.7. 377 378Aqui estão 3 exemplos de como aplicar esses patches:: 379 380 # primeiro, um exemplo de mudança do 5.7 para o 5.8-rc3 381 382 $ cd ~/linux-5.7 # muda para o dir do fonte do 5.7 383 $ patch -p1 < ../patch-5.8-rc3 # aplica o patch do 5.8-rc3 384 $ cd .. 385 $ mv linux-5.7 linux-5.8-rc3 # renomeia o dir do fonte 386 387 # agora vamos mudar do 5.8-rc3 para o 5.8-rc5 388 389 $ cd ~/linux-5.8-rc3 # muda para o dir do 5.8-rc3 390 $ patch -p1 -R < ../patch-5.8-rc3 # reverte o patch do 5.8-rc3 391 $ patch -p1 < ../patch-5.8-rc5 # aplica o novo patch do 5.8-rc5 392 $ cd .. 393 $ mv linux-5.8-rc3 linux-5.8-rc5 # renomeia o dir do fonte 394 395 # por fim, vamos tentar mudar do 5.7.3 para o 5.8-rc5 396 397 $ cd ~/linux-5.7.3 # muda para o dir do fonte do kernel 398 $ patch -p1 -R < ../patch-5.7.3 # reverte o patch do 5.7.3 399 $ patch -p1 < ../patch-5.8-rc5 # aplica o novo patch do 5.8-rc5 400 $ cd .. 401 $ mv linux-5.7.3 linux-5.8-rc5 # renomeia o dir do fonte do kernel 402 403 404Os patches -mm e a árvore linux-next 405==================================== 406 407Os patches -mm são patches experimentais publicados por Andrew Morton. 408 409No passado, a árvore -mm também era usada para testar patches de subsistemas, 410mas essa função agora é realizada por meio da árvore 411`linux-next` (https://www.kernel.org/doc/man-pages/linux-next.html). 412Os mantenedores de subsistemas enviam seus patches primeiro para a linux-next e, 413durante a janela de mesclagem (merge window), enviam-nos diretamente para Linus. 414 415Os patches -mm servem como uma espécie de campo de testes para novos recursos e 416outros patches experimentais que não são mesclados por meio de uma árvore de 417subsistema. Assim que tais patches provam seu valor na -mm por um tempo, Andrew 418os envia para Linus para inclusão na linha principal (mainline). 419 420A árvore linux-next é atualizada diariamente e inclui os patches -mm. Ambas 421estão em constante fluxo e contêm muitos recursos experimentais, uma grande 422quantidade de patches de depuração (debugging) não apropriados para a linha 423principal etc., sendo as mais experimentais das ramificações descritas neste 424documento. 425 426Estes patches não são apropriados para uso em sistemas que devem ser estáveis e 427são mais arriscados de executar do que qualquer uma das outras ramificações 428(certifique-se de ter backups atualizados -- isso vale para qualquer kernel 429experimental, mas ainda mais para patches -mm ou ao usar um kernel da árvore 430linux-next). 431 432O teste dos patches -mm e da linux-next é imensamente apreciado, pois todo o 433objetivo deles é eliminar regressões, travamentos (crashes), bugs de corrupção 434de dados, quebras de compilação (e qualquer outro bug em geral) antes que as 435alterações sejam mescladas na árvore principal do Linus, que é mais estável. 436 437Mas os testadores da -mm e da linux-next devem estar cientes de que quebras são 438mais comuns do que em qualquer outra árvore. 439 440 441Isso conclui esta lista de explicações sobre as várias árvores do kernel. 442Espero que agora você tenha clareza sobre como aplicar os vários patches e 443ajudar a testar o kernel. 444 445Agradecimentos a Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert, 446Johannes Stezenbach, Grant Coady, Pavel Machek e outros que posso ter esquecido 447por suas revisões e contribuições para este documento.