A handful of late-arriving changes, most of which were ready ahead of the

merge window:
 
 - More Portuguese translation updates
 
 - Some docs-build and self-test fixes
 
 - Bring documentation for the user-space access primitives in
   include/linux/uaccess.h into the docs build.  This revealed a number of
   malformed kerneldoc comments, which are fixed in a subsequent tweak to
   uaccess.h.
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCgAtFiEEIw+MvkEiF49krdp9F0NaE2wMflgFAmriEykPHGNvcmJldEBs
 d24ubmV0AAoJEBdDWhNsDH5YC9IH/ikTCYIK+3Nz8odNLbEh505Ug0KDaAK6Cux5
 Wb6eKpMaLfwxMojV80V8/lZMMmKzkeGWRO60TgF4V6MNdziOuj2UoFNIx/M+9jkw
 5kPsc/vwGdtt2bR7FN1GKbchH9sh22Baw0aCTk+ymMMTFqDHDJ7qXrCfvm8MNAXg
 8+xPr9acR4hYy9Bd8HOKx+noym8qmRvLqeznM5hvOBlQtYk5ZJWwIfuiiH61pzyv
 89BrR9fMhObO/5ObSv9OpxFR+28SeB2986zXw1HTyskCrFes9s0Dd6EQfVvL6NxV
 ldCt1odfoyAa5KJurvJ3piILJANrcID5PBDlqN/T8jG9oO6gxRc=
 =xUko
 -----END PGP SIGNATURE-----

Merge tag 'docs-7.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux

Pull more documentation updates from Jonathan Corbet:
 "A handful of late-arriving changes, most of which were ready ahead of
  the merge window:

   - More Portuguese translation updates

   - Some docs-build and self-test fixes

   - Bring documentation for the user-space access primitives
     in include/linux/uaccess.h into the docs build.

     This revealed a number of malformed kerneldoc comments,
     which are fixed in a subsequent tweak to uaccess.h"

* tag 'docs-7.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux:
  uaccess: fix some erroneous kerneldoc comments
  docs/translations/pt_BR: admin-guide: add efi-stub.rst
  docs/translations/pt_BR: admin-guide: add kernel-parameters.rst
  docs/translations/pt_BR: admin-guide: add bootconfig.rst
  docs/translations/pt_BR: admin-guide: add perf-security.rst
  docs/translations/pt_BR: admin-guide: add LSM/index.rst
  docs/translations/pt_BR: admin-guide: add hw-vuln/index.rst
  docs/translations/pt_BR: admin-guide: add cputopology.rst
  docs/translations/pt_BR: admin-guide: add sysctl/index.rst
  docs/translations/pt_BR: admin-guide: add sysfs-rules.rst
  docs/translations/pt_BR: admin-guide: add features.rst
  docs: pt_BR: process: translate userspace debugging guide
  docs: kerneldoc.py: preserve headings in kernel-doc output
  docs: xforms_lists: Handle DECLARE_KHOSER_PTR() struct members
  docs: test_doc_build: don't select urllib3 yanked version
  docs: test_doc_build: address pylint warnings
  docs: test_doc_build: update it to support newer Sphinx versions
  docs: test_doc_build: better handle python version
  docs: admin-guide: Fix typo in kernel-parameters.txt
  docs: core-api: include documentation from linux/uaccess.h
This commit is contained in:
Linus Torvalds 2026-10-29 07:46:22 -10:00
commit cb01c6914e
19 changed files with 1900 additions and 63 deletions

View File

@ -6242,7 +6242,7 @@ Kernel parameters
rcutorture.stall_only= [KNL]
Shut off all rcutorture kthreads other than the
RCU CPU stall-warning test kthreads. The purpose
of this is to test production applictions'
of this is to test production applications'
reactions to CPU stalls, and with minimal
additional overhead. Or you can omit the
stall-warning tests as well and get a heavy

View File

@ -8,6 +8,9 @@ User Space Memory Access
.. kernel-doc:: arch/x86/include/asm/uaccess.h
:internal:
.. kernel-doc:: include/linux/uaccess.h
:internal:
.. kernel-doc:: arch/x86/lib/usercopy_32.c
:export:

View File

@ -38,6 +38,7 @@ from docutils.statemachine import ViewList
from docutils.parsers.rst import directives, Directive
import sphinx
from sphinx.util.docutils import switch_source_input
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util import logging
from pprint import pformat
@ -252,7 +253,7 @@ class KernelDocDirective(Directive):
def do_parse(self, result, node):
with switch_source_input(self.state, result):
self.state.nested_parse(result, 0, node, match_titles=1)
nested_parse_with_titles(self.state, result, node)
def setup_kfiles(app):
global kfiles

View File

@ -0,0 +1,53 @@
.. SPDX-License-Identifier: GPL-2.0
===========================================
Uso dos Módulos de Segurança do Linux (LSM)
===========================================
O framework dos Módulos de Segurança do Linux (LSM - Linux Security Module)
fornece um mecanismo para que várias verificações de segurança sejam interceptadas
por novas extensões do kernel. O nome "módulo" é um pouco impróprio, já que essas
extensões não são, na verdade, módulos carregáveis do kernel. Em vez disso, elas
são selecionáveis em tempo de compilação via CONFIG_DEFAULT_SECURITY e podem ser
substituídas em tempo de inicialização pelo argumento de linha de comando do
kernel ``"security=..."``, no caso em que múltiplos LSMs foram compilados em um
determinado kernel.
Os principais usuários da interface LSM são as extensões de Controle de Acesso
Obrigatório (MAC - Mandatory Access Control), que fornecem uma política de
segurança abrangente. Os exemplos incluem SELinux, Smack, Tomoyo e AppArmor. Além
das extensões MAC maiores, outras extensões podem ser construídas usando o LSM
para fornecer alterações específicas na operação do sistema quando esses ajustes
não estão disponíveis na funcionalidade principal do próprio Linux.
Os módulos de capacidades do Linux sempre serão incluídos. Isso pode ser seguido
por qualquer número de módulos "menores" (minor) e no máximo um módulo "maior"
(major). Para obter mais detalhes sobre capacidades, consulte ``capabilities(7)``
no projeto Linux man-pages.
Uma lista dos módulos de segurança ativos pode ser encontrada lendo
``/sys/kernel/security/lsm``. Esta é uma lista separada por vírgulas e sempre
incluirá o módulo de capacidade. A lista reflete a ordem na qual as verificações
são feitas. O módulo de capacidade sempre será o primeiro, seguido por quaisquer
módulos "menores" (por exemplo, Yama) e depois pelo módulo "maior" (por exemplo,
SELinux), se houver um configurado.
Os atributos de processo associados aos módulos de segurança "maiores" devem ser
acessados e mantidos usando os arquivos especiais em ``/proc/.../attr``. Um módulo
de segurança pode manter um subdiretório específico do módulo lá, nomeado após o
módulo. ``/proc/.../attr/smack`` é fornecido pelo módulo de segurança Smack e
contém todos os seus arquivos especiais. Os arquivos diretamente em
``/proc/.../attr`` permanecem como interfaces legadas para módulos que fornecem
subdiretórios.
Todolist:
* apparmor
* LoadPin
* SELinux
* Smack
* tomoyo
* Yama
* SafeSetID
* ipe
* landlock

View File

@ -0,0 +1,425 @@
.. SPDX-License-Identifier: GPL-2.0
====================
Configuração de boot
====================
:Autor: Masami Hiramatsu <mhiramat@kernel.org>
Visão geral
===========
A configuração de boot expande a linha de comando atual do kernel para suportar
dados adicionais de chave-valor ao inicializar o kernel de forma eficiente.
Isso permite que os administradores passem um arquivo de configuração estruturado
por chaves.
Sintaxe do arquivo de configuração
==================================
A sintaxe de configuração de boot é uma estrutura simples de chave-valor. Cada
chave consiste em palavras conectadas por pontos, e a chave e o valor são
conectados por ``=``. A string de valor deve ser terminada pelos seguintes
delimitadores descritos abaixo.
Cada palavra-chave deve conter apenas letras do alfabeto, números, traço (``-``)
ou sublinhado (``_``). E cada valor contém apenas caracteres imprimíveis ou espaços,
exceto delimitadores como ponto e vírgula (``;``), quebra de linha (``\n``),
vírgula (``,``), cerquilha (``#``) e chave de fechamento (``}``).
Se o ``=`` for seguido por espaços em branco até um desses delimitadores, a chave
será atribuída a um valor vazio.
Para arrays, os valores do array são separados por vírgula (``,``), e comentários
e quebras de linha com nova linha (``\n``) são permitidos entre os valores do array
para facilitar a legibilidade. Assim, a primeira entrada do array deve estar na
mesma linha da chave.::
CHAVE[.PALAVRA[...]] = VALOR[, VALOR2[...]][;]
Diferente da sintaxe de linha de comando do kernel, espaços em branco (incluindo
tabs) são ignorados ao redor da vírgula e do ``=``.
Se você quiser usar esses delimitadores em um valor, pode usar aspas duplas
(``"VALOR"``) ou aspas simples (``'VALOR'``) para colocá-lo entre aspas. Observe
que você não pode escapar essas aspas.
Pode haver uma chave que não tenha valor ou tenha um valor vazio. Essas chaves
são usadas para verificar se a chave existe ou não (como um booleano).
Sintaxe de chave-valor
----------------------
A sintaxe do arquivo de configuração de boot permite que o usuário mescle chaves
com palavras parcialmente iguais usando chaves (braces). Por exemplo::
foo.bar.baz = value1
foo.bar.qux.quux = value2
Elas também podem ser escritas assim::
foo.bar {
baz = value1
qux.quux = value2
}
Ou de forma mais concisa, escrita da seguinte maneira::
foo.bar { baz = value1; qux.quux = value2 }
Em ambos os estilos, as mesmas palavras-chave são mescladas automaticamente ao
serem analisadas no momento da inicialização. Assim, você pode anexar árvores ou
pares de chave-valor semelhantes.
Valores com a mesma chave
-------------------------
É proibido que dois ou mais valores ou arrays compartilhem a mesma chave.
Por exemplo::
foo = bar, baz
foo = qux # !ERRO! não podemos redefinir a mesma chave
Se você quiser atualizar o valor, deve usar o operador de substituição (override)
``:=`` explicitamente. Por exemplo::
foo = bar, baz
foo := qux
então, ``qux`` é atribuído à chave ``foo``. Isso é útil para sobrescrever o
valor padrão adicionando bootconfigs personalizados (parciais) sem precisar
analisar o bootconfig padrão.
Se você quiser anexar o valor a uma chave existente como membro de um array,
pode usar o operador ``+=``. Por exemplo::
foo = bar, baz
foo += qux
Neste caso, a chave ``foo`` conterá ``bar``, ``baz`` e ``qux``.
Além disso, subchaves e um valor podem coexistir sob uma chave pai.
Por exemplo, a seguinte configuração é permitida::
foo = value1
foo.bar = value2
foo := value3 # Isto atualizará o valor de foo.
Observe que, como não há sintaxe para colocar um valor puro diretamente sob uma
chave estruturada, você deve defini-lo fora das chaves. Por exemplo::
foo {
bar = value1
bar {
baz = value2
qux = value3
}
}
Além disso, a ordem do nó de valor sob uma chave é fixa. Se houver um valor e
subchaves, o valor será sempre o primeiro nó filho da chave. Portanto, se o
usuário especificar subchaves primeiro, por exemplo::
foo.bar = value1
foo = value2
No programa (e em /proc/bootconfig), ele será exibido conforme abaixo::
foo = value2
foo.bar = value1
Comentários
-----------
A sintaxe de configuração aceita comentários no estilo shell-script. Os comentários
iniciados com cerquilha ("#") até a quebra de linha ("\n") serão ignorados.
::
# linha de comentário
foo = value # valor atribuído a foo.
bar = 1, # 1º elemento
2, # 2º elemento
3 # 3º elemento
Isto é analisado como abaixo::
foo = value
bar = 1, 2, 3
Observe que você NÃO pode colocar um comentário ou uma quebra de linha entre o
valor e o delimitador (``,`` ou ``;``). Isso significa que a seguinte configuração
possui um erro de sintaxe::
key = 1 # comentário
,2
/proc/bootconfig
================
/proc/bootconfig é uma interface de espaço de usuário da configuração de boot.
Diferente de /proc/cmdline, este arquivo exibe a lista no estilo chave-valor.
Cada par chave-valor é mostrado em cada linha no seguinte formato::
CHAVE[.PALAVRAS...] = "[VALOR]"[,"VALOR2"...]
Inicializando o kernel com um Boot Config
=========================================
Existem duas opções para inicializar o kernel com bootconfig: anexar o bootconfig
à imagem initrd ou embuti-lo no próprio kernel.
Anexando um Boot Config ao Initrd
---------------------------------
Como o arquivo de configuração de boot é carregado com o initrd por padrão, ele
será adicionado ao final do arquivo de imagem do initrd (initramfs) com
preenchimento (padding), tamanho, checksum e palavra mágica de 12 bytes conforme
abaixo.
[initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
Os campos de tamanho (size) e checksum são valores de 32 bits sem sinal em little endian.
Quando a configuração de boot é adicionada à imagem do initrd, o tamanho total
do arquivo é alinhado a 4 bytes. Para preencher a lacuna, caracteres nulos
(``\0``) serão adicionados. Assim, ``size`` é o comprimento do arquivo bootconfig
+ bytes de preenchimento.
O kernel Linux decodifica a última parte da imagem do initrd na memória para
obter os dados de configuração de boot.
Por causa desse método "piggyback", não há necessidade de alterar ou atualizar o
carregador de inicialização (boot loader) e a própria imagem do kernel, desde que
o boot loader passe o tamanho correto do arquivo initrd. Se, por qualquer motivo,
o boot loader passar um tamanho maior, o kernel não conseguirá encontrar os
dados do bootconfig.
Para realizar esta operação, o kernel Linux fornece o comando ``bootconfig`` sob
tools/bootconfig, que permite ao administrador aplicar ou excluir o arquivo de
configuração na/da imagem do initrd. Você pode compilá-lo com o seguinte comando::
# make -C tools/bootconfig
Para adicionar seu arquivo de configuração de boot à imagem do initrd, execute o
bootconfig conforme abaixo (dados antigos são removidos automaticamente se existirem)::
# tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z
Para remover a configuração da imagem, você pode usar a opção -d como abaixo::
# tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z
Em seguida, adicione "bootconfig" na linha de comando normal do kernel para instruir
o kernel a procurar pelo bootconfig no final do arquivo initrd.
Como alternativa, compile seu kernel com a opção Kconfig ``CONFIG_BOOT_CONFIG_FORCE``
selecionada.
Embutindo um Boot Config no kernel
----------------------------------
Se você não puder usar initrd, também poderá embutir o arquivo bootconfig no
kernel através de opções do Kconfig. Nesse caso, você precisa recompilar o
kernel com as seguintes configurações::
CONFIG_BOOT_CONFIG_EMBED=y
CONFIG_BOOT_CONFIG_EMBED_FILE="/CAMINHO/PARA/ARQUIVO/BOOTCONFIG"
``CONFIG_BOOT_CONFIG_EMBED_FILE`` requer um caminho absoluto ou um caminho
relativo para o arquivo bootconfig a partir da árvore de código-fonte ou da
árvore de objetos. O kernel o embutirá como o bootconfig padrão.
Assim como ao anexar o bootconfig ao initrd, você precisa da opção ``bootconfig``
na linha de comando do kernel para habilitar o bootconfig embutido ou,
alternativamente, compilar seu kernel com a opção Kconfig
``CONFIG_BOOT_CONFIG_FORCE`` selecionada.
Observe que, mesmo se você definir esta opção, poderá sobrescrever o bootconfig
embutido por outro bootconfig anexado ao initrd.
Renderizando chaves kernel.* embutidas em tempo de compilação
-------------------------------------------------------------
Por padrão, o bootconfig embutido (``CONFIG_BOOT_CONFIG_EMBED=y``) é analisado
em tempo de execução, após ``parse_early_param()`` já ter sido executado. Os
tratadores de parâmetros iniciais (early parameters) (``mem=``, ``earlycon=``,
``loglevel=``, ...) não conseguem, portanto, ver valores fornecidos através da
subárvore ``kernel`` embutida.
A opção ``CONFIG_CMDLINE_FROM_BOOTCONFIG`` resolve isso renderizando a subárvore
``kernel`` de ``CONFIG_BOOT_CONFIG_EMBED_FILE`` em uma string de cmdline plana em
tempo de compilação do kernel (via ``tools/bootconfig -C``) e prefixando-a a
``boot_command_line`` durante a configuração arquitetural inicial, de modo que
as chaves fiquem visíveis para ``parse_early_param()``.
A opção requer ``CONFIG_BOOT_CONFIG_EMBED=y``, um ``CONFIG_BOOT_CONFIG_EMBED_FILE``
não vazio, ``CONFIG_CMDLINE`` vazio e uma arquitetura que selecione
``CONFIG_ARCH_SUPPORTS_CMDLINE_FROM_BOOTCONFIG``. Atualmente apenas x86 a seleciona;
em outras arquiteturas, o bootconfig embutido ainda funciona, mas apenas por meio
do analisador tardio em tempo de execução.
A mesma ativação explícita de ``bootconfig`` se aplica como em outros lugares:
as chaves renderizadas são prefixadas apenas quando ``bootconfig`` (em qualquer
forma) aparece na linha de comando do kernel, ou quando ``CONFIG_BOOT_CONFIG_FORCE``
está definido, cujo padrão é ``y`` quando ``CONFIG_BOOT_CONFIG_EMBED`` está definido.
Por exemplo, dado::
kernel {
loglevel = 7
mem = 4G
}
o kernel inicializa como se ``loglevel=7 mem=4G`` tivesse sido prefixado à linha
de comando do carregador de inicialização, com os valores visíveis para os
tratadores analisados precocemente. Valores separados por vírgula ainda são
expandidos em múltiplas entradas de linha de comando de acordo com a convenção
de array do bootconfig -- o ``kernel.earlycon = "uart8250,io,0x3f8"`` embutido
deve estar entre aspas para resultar em uma única entrada ``earlycon=``, exatamente
como no analisador em tempo de execução.
Se a string renderizada não couber em ``COMMAND_LINE_SIZE`` juntamente com a
linha de comando existente, o prefixo será ignorado e um erro será registrado,
de modo que um bootconfig embutido superdimensionado não possa travar a inicialização.
Interação com outras fontes de linha de comando e bootconfig
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Com ``CONFIG_CMDLINE_FROM_BOOTCONFIG=y``, a subárvore ``kernel`` renderizada
comporta-se como uma linha de comando em tempo de compilação (semelhante a
``CONFIG_CMDLINE``), e não como uma fonte de bootconfig. Ela é prefixada a
``boot_command_line`` em ``setup_arch()``, antes de ``parse_early_param()`` e
muito antes de o analisador em tempo de execução inspecionar um initrd. As opções
podem chegar ao kernel a partir de até quatro locais:
- Linha de comando do carregador de inicialização (bootloader): os argumentos
que o carregador de inicialização passa. A linha de comando embutida é
prefixada na frente deles, portanto, para parâmetros onde o último vence
(last-one-wins), uma opção do bootloader ainda sobrescreve o valor embutido.
Visível em /proc/cmdline.
- Linha de comando embutida (esta opção): a subárvore ``kernel`` renderizada,
prefixada precocemente para ser vista por ``parse_early_param()``. Visível em
/proc/cmdline.
- Bootconfig do initrd: analisado tardiamente em ``setup_boot_config()``; suas
chaves ``kernel`` são colocadas antes de ``boot_command_line``, ou seja, antes
da linha de comando embutida, portanto, a regra do último vencedor favorece os
valores embutidos. Como uma fonte de bootconfig, um bootconfig do initrd ainda
substitui o bootconfig embutido. Visível em /proc/cmdline e /proc/bootconfig.
- Bootconfig embutido (tempo de execução): analisado tardiamente, apenas quando
nenhum bootconfig do initrd estiver presente. Visível em /proc/cmdline e
/proc/bootconfig.
Assim, com esta opção, os valores ``kernel.*`` embutidos têm precedência sobre os
valores ``kernel.*`` de um bootconfig do initrd: para parâmetros iniciais, o initrd
ainda não foi analisado e, para parâmetros comuns, as chaves embutidas chegam mais
tarde na linha de comando. Se você precisa que um bootconfig do initrd sobrescreva
as chaves ``kernel.*`` embutidas, deixe esta opção desativada e confie no analisador
em tempo de execução.
A string renderizada faz parte da linha de comando, portanto aparece em
/proc/cmdline. Ela deliberadamente não é mostrada em /proc/bootconfig: esse
arquivo continua relatando a árvore de bootconfig analisada -- o bootconfig do
initrd se presente, caso contrário o bootconfig embutido -- independentemente de a
renderização da linha de comando em tempo de compilação estar ativada.
Parâmetros do kernel via Boot Config
====================================
Além da linha de comando do kernel, a configuração de boot pode ser usada para
passar os parâmetros do kernel. Todos os pares chave-valor sob a chave ``kernel``
serão passados diretamente para a linha de comando do kernel. Além disso, os pares
chave-valor sob ``init`` serão passados para o processo init via linha de comando.
Os parâmetros são concatenados com a string de linha de comando do kernel fornecida
pelo usuário na seguinte ordem, de modo que o parâmetro de linha de comando possa
sobrescrever os parâmetros de bootconfig (isso depende de como o subsistema lida com
parâmetros, mas em geral, o parâmetro anterior será sobrescrito pelo posterior)::
[bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]
Aqui está um exemplo de arquivo bootconfig para parâmetros de kernel/init::
kernel {
root = 01234567-89ab-cdef-0123-456789abcd
}
init {
splash
}
Isto será copiado na string de linha de comando do kernel da seguinte forma::
root="01234567-89ab-cdef-0123-456789abcd" -- splash
Se o usuário fornecer alguma outra linha de comando como::
ro bootconfig -- quiet
A linha de comando final do kernel será a seguinte::
root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet
Limitações do arquivo de configuração
=====================================
Atualmente, o tamanho máximo da configuração é de 32 KB e o total de palavras-chave
(não entradas de chave-valor) deve ser inferior a 1024 nós.
Nota: este não é o número de entradas, mas de nós; uma entrada deve consumir mais
de 2 nós (uma palavra-chave e um valor). Portanto, teoricamente, haverá até 512
pares chave-valor. Se as chaves contiverem 3 palavras em média, poderá conter 256
pares chave-valor. Na maioria dos casos, o número de itens de configuração estará
abaixo de 100 entradas e será menor que 8 KB, o que seria suficiente.
Se o número de nós exceder 1024, o analisador retornará um erro mesmo se o tamanho
do arquivo for menor que 32 KB. (Observe que esse tamanho máximo não inclui os
caracteres nulos de preenchimento.)
De qualquer forma, como o comando bootconfig verifica isso ao anexar uma configuração
de boot à imagem initrd, o usuário pode perceber antes da inicialização.
APIs do Bootconfig
==================
O usuário pode consultar ou iterar sobre pares chave-valor; também é possível
encontrar um nó de chave raiz (prefixo) e encontrar chaves-valores sob esse nó.
Se você tiver uma string de chave, poderá consultar o valor diretamente com a chave
usando xbc_find_value(). Se quiser saber quais chaves existem no bootconfig, pode
usar xbc_for_each_key_value() para iterar sobre os pares chave-valor.
Observe que você precisa usar xbc_array_for_each_value() para acessar o valor de
cada array, por exemplo::
vnode = NULL;
xbc_find_value("key.word", &vnode);
if (vnode && xbc_node_is_array(vnode))
xbc_array_for_each_value(vnode, value) {
printk("%s ", value);
}
Se você quiser focar em chaves que tenham uma string de prefixo, pode usar
xbc_find_node() para encontrar um nó pela string de prefixo e iterar pelas chaves
sob o nó de prefixo com xbc_node_for_each_key_value().
Mas o uso mais típico é obter o valor nomeado sob o prefixo ou obter o array
nomeado sob o prefixo, como abaixo::
root = xbc_find_node("key.prefix");
value = xbc_node_find_value(root, "option", &vnode);
...
xbc_node_for_each_array_value(root, "array-option", value, anode) {
...
}
Isso acessa um valor de "key.prefix.option" e um array de "key.prefix.array-option".
O bloqueio (locking) não é necessário, pois após a inicialização, a configuração
torna-se somente leitura. Todos os dados e chaves devem ser copiados se você
precisar modificá-los.
Funções e estruturas
====================
Para a documentação kernel-doc das definições, consulte:
- include/linux/bootconfig.h
- lib/bootconfig.c

View File

@ -0,0 +1,105 @@
.. SPDX-License-Identifier: GPL-2.0
================================================================
Como as informações de topologia de CPU são exportadas via sysfs
================================================================
As informações de topologia de CPU são exportadas via sysfs. Os itens
(atributos) são semelhantes à saída de /proc/cpuinfo em algumas arquiteturas.
Eles residem em /sys/devices/system/cpu/cpuX/topology/. Por favor, consulte o
arquivo de ABI: Documentation/ABI/stable/sysfs-devices-system-cpu.
O arquivo independente de arquitetura, drivers/base/topology.c, exporta esses
atributos. No entanto, os arquivos do sysfs relacionados à hierarquia de die,
cluster, book e drawer só serão criados se uma arquitetura fornecer as macros
relacionadas, conforme descrito abaixo.
Para que uma arquitetura ofereça suporte a esse recurso, ela deve definir
algumas dessas macros em include/asm-XXX/topology.h::
#define topology_physical_package_id(cpu)
#define topology_die_id(cpu)
#define topology_cluster_id(cpu)
#define topology_core_id(cpu)
#define topology_book_id(cpu)
#define topology_drawer_id(cpu)
#define topology_sibling_cpumask(cpu)
#define topology_core_cpumask(cpu)
#define topology_cluster_cpumask(cpu)
#define topology_die_cpumask(cpu)
#define topology_book_cpumask(cpu)
#define topology_drawer_cpumask(cpu)
O tipo das ``macros **_id`` é int.
O tipo das ``macros **_cpumask`` é ``(const) struct cpumask *``. Estas últimas
correspondem aos atributos apropriados ``**_siblings`` do sysfs (exceto por
topology_sibling_cpumask(), que corresponde a thread_siblings).
Para manter a consistência em todas as arquiteturas, include/linux/topology.h
fornece definições padrão para qualquer uma das macros acima que não estejam
definidas em include/asm-XXX/topology.h:
1) topology_physical_package_id: -1
2) topology_die_id: -1
3) topology_cluster_id: -1
4) topology_core_id: 0
5) topology_book_id: -1
6) topology_drawer_id: -1
7) topology_sibling_cpumask: apenas a CPU fornecida
8) topology_core_cpumask: apenas a CPU fornecida
9) topology_cluster_cpumask: apenas a CPU fornecida
10) topology_die_cpumask: apenas a CPU fornecida
11) topology_book_cpumask: apenas a CPU fornecida
12) topology_drawer_cpumask: apenas a CPU fornecida
Além disso, as informações de topologia de CPU são fornecidas sob
/sys/devices/system/cpu e incluem estes arquivos. A fonte interna para a saída
está entre colchetes ("[]").
=========== ==========================================================
kernel_max: o índice máximo de CPU permitido pela configuração do kernel.
[NR_CPUS-1]
offline: CPUs que não estão online porque foram desligadas via
HOTPLUG ou excedem o limite de CPUs permitido pela
configuração do kernel (kernel_max acima).
[~cpu_online_mask + cpus >= NR_CPUS]
online: CPUs que estão online e sendo escalonadas [cpu_online_mask]
possible: CPUs para as quais foram alocados recursos e que podem ser
colocadas online se estiverem presentes. [cpu_possible_mask]
present: CPUs que foram identificadas como presentes no
sistema. [cpu_present_mask]
=========== ==========================================================
O formato para a saída acima é compatível com cpulist_parse()
[veja <linux/cpumask.h>]. Alguns exemplos a seguir.
Neste exemplo, existem 64 CPUs no sistema, mas as cpus 32-63 excedem
o máximo do kernel, que está limitado a 0..31 devido à opção de
configuração NR_CPUS ser 32. Observe também que as CPUs 2 e 4-31 não estão
online, mas poderiam ser colocadas online, pois estão tanto presentes
quanto possíveis::
kernel_max: 31
offline: 2,4-31,32-63
online: 0-1,3
possible: 0-31
present: 0-31
Neste exemplo, a opção de configuração NR_CPUS é 128, mas o kernel foi
iniciado com possible_cpus=144. Existem 4 CPUs no sistema e a cpu2
foi colocada offline manualmente (e é a única CPU que pode ser colocada
online.)::
kernel_max: 127
offline: 2,4-127,128-143
online: 0-1,3
possible: 0-127
present: 0-3
Consulte Documentation/core-api/cpu_hotplug.rst para o parâmetro de inicialização
do kernel possible_cpus=NUM, bem como para obter mais informações sobre as
várias cpumasks.

View File

@ -0,0 +1,102 @@
.. SPDX-License-Identifier: GPL-2.0
=================
O EFI Boot Stub
=================
Nas plataformas x86 e ARM, uma zImage/bzImage do kernel pode se passar por
uma imagem PE/COFF, convencendo assim os carregadores de firmware EFI a
carregá-la como um executável EFI. O código que modifica o cabeçalho da bzImage,
juntamente com o ponto de entrada específico do EFI para o qual o carregador de
firmware salta, são conhecidos coletivamente como o "EFI boot stub", e residem
em arch/x86/boot/header.S e drivers/firmware/efi/libstub/x86-stub.c, respectivamente.
Para ARM, o stub EFI é implementado em arch/arm/boot/compressed/efi-header.S e
drivers/firmware/efi/libstub/arm32-stub.c. O código do stub EFI compartilhado
entre arquiteturas está em drivers/firmware/efi/libstub.
Para arm64, não há suporte a kernel compactado, portanto a própria Imagem se
passa por uma imagem PE/COFF e o stub EFI é vinculado diretamente ao kernel. O
stub EFI para arm64 reside em drivers/firmware/efi/libstub/arm64.c e
drivers/firmware/efi/libstub/arm64-stub.c.
Ao usar o EFI boot stub, é possível inicializar um kernel Linux sem o uso de um
carregador de boot EFI convencional, como o grub ou elilo. Como o EFI boot stub
desempenha as tarefas de um carregador de inicialização, em certo sentido ele *É*
o carregador de inicialização.
O EFI boot stub é ativado com a opção de kernel CONFIG_EFI_STUB.
Como instalar bzImage.efi
-------------------------
A bzImage localizada em arch/x86/boot/bzImage deve ser copiada para a Partição
de Sistema EFI (ESP - EFI System Partition) e renomeada com a extensão ".efi".
Sem a extensão, o carregador de firmware EFI se recusará a executá-la. Não é
possível executar bzImage.efi a partir dos sistemas de arquivos normais do Linux
porque o firmware EFI não possui suporte para eles. Para ARM, a
arch/arm/boot/zImage deve ser copiada para a partição de sistema e pode não
precisar ser renomeada. Da mesma forma, para arm64, arch/arm64/boot/Image deve
ser copiada, mas não necessariamente renomeada.
Passando parâmetros do kernel a partir do shell EFI
---------------------------------------------------
Argumentos para o kernel podem ser passados após bzImage.efi, por exemplo::
fs0:> bzImage.efi console=ttyS0 root=/dev/sda4
A opção "initrd="
-----------------
Como a maioria dos carregadores de inicialização, o stub EFI permite que o
usuário especifique múltiplos arquivos initrd usando a opção "initrd=". Este é
o único parâmetro de linha de comando específico do stub EFI; tudo o mais é
passado para o kernel quando ele inicializa.
O caminho para o arquivo initrd deve ser um caminho absoluto a partir do início
da ESP; nomes de caminhos relativos não funcionam. Além disso, o caminho é no
estilo EFI e os elementos de diretório devem ser separados com barras invertidas
(\). Por exemplo, dada a seguinte estrutura de diretórios::
fs0:>
Kernels\
bzImage.efi
initrd-large.img
Ramdisks\
initrd-small.img
initrd-medium.img
para inicializar com o arquivo initrd-large.img se o diretório de trabalho atual
for fs0:\Kernels, o seguinte comando deve ser usado::
fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img
Observe como bzImage.efi pode ser especificado com um caminho relativo. Isso ocorre
porque a imagem que estamos executando é interpretada pelo shell EFI, que entende
caminhos relativos, enquanto o restante da linha de comando é passado para bzImage.efi.
.. hint::
Também é possível fornecer um initrd usando um protocolo UEFI específico do
Linux no momento da inicialização. Consulte :ref:`pe-coff-entry-point` para
obter detalhes.
A opção "dtb="
--------------
Para as arquiteturas ARM e arm64, uma árvore de dispositivos (device tree) deve ser
fornecida ao kernel. Normalmente, o firmware deve fornecer a árvore de dispositivos
através da EFI CONFIGURATION TABLE. No entanto, a opção de linha de comando "dtb="
pode ser usada para sobrescrever a árvore de dispositivos fornecida pelo firmware
ou para fornecer uma quando o firmware não puder fazê-lo.
Observe: O firmware adiciona informações de configuração em tempo de execução à
árvore de dispositivos antes de inicializar o kernel. Se dtb= for usado para
sobrescrever a árvore de dispositivos, quaisquer dados em tempo de execução
fornecidos pelo firmware serão perdidos. A opção dtb= deve ser usada apenas como
uma ferramenta de depuração ou como último recurso quando uma árvore de dispositivos
não for fornecida na EFI CONFIGURATION TABLE.
"dtb=" é processado da mesma maneira que a opção "initrd=" descrita acima.

View File

@ -0,0 +1,3 @@
.. SPDX-License-Identifier: GPL-2.0
.. kernel-feat:: features

View File

@ -0,0 +1,30 @@
.. SPDX-License-Identifier: GPL-2.0
============================
Vulnerabilidades de hardware
============================
Esta seção descreve vulnerabilidades de CPU e fornece uma visão geral das
possíveis mitigações, juntamente com orientações para a seleção de mitigações,
caso sejam configuráveis em tempo de compilação, inicialização ou execução.
Todolist:
* attack_vector_controls
* spectre
* l1tf
* mds
* tsx_async_abort
* multihit
* special-register-buffer-data-sampling
* core-scheduling
* l1d_flush
* processor_mmio_stale_data
* cross-thread-rsb
* srso
* gather_data_sampling
* reg-file-data-sampling
* rsb
* old_microcode
* indirect-target-selection
* vmscape

View File

@ -26,38 +26,44 @@ etc.
README
devices
Todolist:
* features
features
Uma grande parte da interface administrativa do kernel são os sistemas de
arquivos virtuais /proc e sysfs; estes documentos descrevem como interagir
com eles.
.. toctree::
:maxdepth: 1
sysfs-rules
sysctl/index
cputopology
Todolist:
* sysfs-rules
* sysctl/index
* cputopology
* abi
Documentação relacionada à segurança:
Todolist:
.. toctree::
:maxdepth: 1
* hw-vuln/index
* LSM/index
* perf-security
hw-vuln/index
LSM/index
perf-security
Inicializando o kernel
----------------------
.. toctree::
:maxdepth: 1
bootconfig
kernel-parameters
efi-stub
Todolist:
* bootconfig
* kernel-parameters
* efi-stub
* initrd
Rastreando e identificando problemas

View File

@ -0,0 +1,134 @@
.. SPDX-License-Identifier: GPL-2.0
Os parâmetros de linha de comando do kernel
===========================================
A seguir está uma lista consolidada dos parâmetros do kernel conforme
implementados pelas macros __setup(), early_param(), core_param() e
module_param(), ordenados na ordem do dicionário inglês (definida como ignorar
toda a pontuação e ordenar dígitos antes de letras sem distinção entre
maiúsculas e minúsculas), e com descrições onde conhecidas.
O kernel analisa os parâmetros da linha de comando do kernel até "``--``";
se ele não reconhecer um parâmetro e este não contiver um '.', o parâmetro
será passado para o init: parâmetros com '=' vão para o ambiente do init,
outros são passados como argumentos de linha de comando para o init.
Tudo após "``--``" é passado como argumento para o init.
Os parâmetros de módulo podem ser especificados de duas maneiras: através da
linha de comando do kernel com um prefixo de nome de módulo, ou via modprobe,
por exemplo::
(linha de comando do kernel) usbcore.blinkenlights=1
(linha de comando do modprobe) modprobe usbcore blinkenlights=1
Os parâmetros para módulos compilados embutidos no kernel precisam ser
especificados na linha de comando do kernel. O modprobe examina a linha de
comando do kernel (/proc/cmdline) e coleta parâmetros de módulo ao carregar um
módulo, de modo que a linha de comando do kernel também pode ser usada para
módulos carregáveis.
Este documento pode não estar totalmente atualizado e abrangente. O comando
"modinfo -p ${nomedomodulo}" exibe uma lista atual de todos os parâmetros de um
módulo carregável. Módulos carregáveis, após serem carregados no kernel em
execução, também revelam seus parâmetros em /sys/module/${nomedomodulo}/parameters/.
Alguns desses parâmetros podem ser alterados em tempo de execução pelo comando
``echo -n ${valor} > /sys/module/${nomedomodulo}/parameters/${param}``.
Tratamento especial
-------------------
Hífens (traços) e sublinhados são equivalentes em nomes de parâmetros, portanto::
log_buf_len=1M print-fatal-signals=1
também pode ser inserido como::
log-buf-len=1M print_fatal_signals=1
Aspas duplas podem ser usadas para proteger espaços nos valores, por exemplo::
param="spaces in here"
Listas de CPUs
~~~~~~~~~~~~~~
Alguns parâmetros do kernel recebem uma lista de CPUs como valor, por exemplo:
isolcpus, nohz_full, irqaffinity, rcu_nocbs. O formato desta lista é:
<número da cpu>,...,<número da cpu>
ou
<número da cpu>-<número da cpu>
(deve ser um intervalo positivo em ordem crescente)
ou uma mistura
<número da cpu>,...,<número da cpu>-<número da cpu>
Observe que, para o caso especial de um intervalo, é possível dividir o intervalo em
grupos de tamanhos iguais e, para cada grupo, usar uma determinada quantidade a
partir do início desse grupo:
<número da cpu>-<número da cpu>:<tamanho usado>/<tamanho do grupo>
Por exemplo, pode-se adicionar à linha de comando o seguinte parâmetro:
isolcpus=1,2,10-20,100-2000:2/25
onde o item final representa as CPUs 100,101,125,126,150,151,...
O valor "N" pode ser usado para representar a última CPU numericamente no sistema,
ou seja, "foo_cpus=16-N" seria equivalente a "16-31" em um sistema de 32 núcleos.
Tenha em mente que "N" é dinâmico; portanto, se alterações no sistema fizerem com
que a largura do bitmap mude, como menos núcleos na lista de CPUs, N e quaisquer
intervalos que usem N também mudarão. Use o mesmo em um sistema pequeno de 4 núcleos,
e "16-N" se tornará "16-3", e agora a mesma entrada de boot será sinalizada como
inválida (início > fim).
O nome de grupo especial tolerante a maiúsculas/minúsculas "all" tem o significado
de selecionar todas as CPUs, de modo que "nohz_full=all" seja o equivalente a
"nohz_full=0-N".
A semântica de "N" e "all" é suportada em nível de bitmaps e é válida para todos
os usuários de bitmap_parselist().
Sufixos métricos
~~~~~~~~~~~~~~~~
O sufixo [KMG] é comumente descrito após vários valores de parâmetros do kernel.
Os sufixos 'K', 'M', 'G', 'T', 'P' e 'E' são permitidos. Essas letras representam
os multiplicadores _binários_ 'Quilo', 'Mega', 'Giga', 'Tera', 'Peta' e 'Exa',
equivalendo a 2^10, 2^20, 2^30, 2^40, 2^50 e 2^60 bytes, respectivamente. Esses
sufixos de letras também podem ser totalmente omitidos.
Opções de compilação do kernel
------------------------------
Os parâmetros listados abaixo só são válidos se certas opções de compilação do
kernel foram ativadas e se o respectivo hardware estiver presente. Esta lista deve
ser mantida em ordem alfabética. O texto entre colchetes no início de cada descrição
informa as restrições sob as quais um parâmetro é aplicável.
Os parâmetros indicados com BOOT são, na verdade, interpretados pelo carregador
de inicialização e não têm significado diretamente para o kernel.
Não modifique a sintaxe dos parâmetros do carregador de inicialização sem extrema
necessidade ou coordenação com <Documentation/arch/x86/boot.rst>.
Existem também parâmetros do kernel específicos de arquitetura não documentados aqui.
Observe que TODOS os parâmetros do kernel listados abaixo DISTINGUEM MAIÚSCULAS DE
MINÚSCULAS, e que um = final no nome de qualquer parâmetro indica que o parâmetro
será inserido como uma variável de ambiente, enquanto sua ausência indica que ele
aparecerá como um argumento do kernel legível via /proc/cmdline por programas em
execução assim que o sistema estiver ativo.
O número de parâmetros do kernel não é limitado, mas o comprimento da linha de
comando completa (parâmetros incluindo espaços, etc.) é limitado a um número fixo
de caracteres. Este limite depende da arquitetura e varia entre 256 e 4096 caracteres.
Ele é definido no arquivo ./include/uapi/asm-generic/setup.h como COMMAND_LINE_SIZE.
.. include:: ../../../admin-guide/kernel-parameters.txt
:literal:

View File

@ -0,0 +1,328 @@
.. SPDX-License-Identifier: GPL-2.0
Segurança das ferramentas e eventos Perf
========================================
Visão geral
-----------
O uso dos Contadores de Desempenho para Linux (perf_events) [1]_ , [2]_ , [3]_
pode impor um risco considerável de vazamento de dados confidenciais acessados
por processos monitorados. O vazamento de dados é possível tanto em cenários de
uso direto da API de chamadas de sistema perf_events [2]_ quanto por meio de
arquivos de dados gerados pelo utilitário em modo de usuário da ferramenta
Perf (Perf) [3]_ , [4]_ . O risco depende da natureza dos dados que as unidades
de monitoramento de desempenho (PMU - Performance Monitoring Units) do
perf_events [2]_ e o Perf coletam e expõem para análise de desempenho.
Os dados de sistema e de desempenho coletados podem ser divididos em várias
categorias:
1. Dados de configuração de hardware e software do sistema, por exemplo: um
modelo de CPU e sua configuração de cache, a quantidade de memória disponível
e sua topologia, versões do kernel e do Perf utilizadas, configuração de
monitoramento de desempenho incluindo tempo de experimento, configuração de
eventos, parâmetros de linha de comando do Perf, etc.
2. Caminhos de módulos de usuário e de kernel e seus endereços de carregamento com
tamanhos, nomes de processos e threads com seus PIDs e TIDs, registros de data
e hora (timestamps) para eventos capturados de hardware e software.
3. Conteúdo de contadores de software do kernel (por exemplo, para trocas de contexto,
falhas de página, migrações de CPU), contadores arquiteturais de desempenho de
hardware (PMC) [8]_ e registradores específicos de modelo (MSR) [9]_ que fornecem
métricas de execução para várias partes monitoradas do sistema (por exemplo,
controlador de memória (IMC), interconexão (QPI/UPI) ou contadores uncore
periféricos (PCIe)) sem atribuição direta a qualquer estado de contexto de execução.
4. Conteúdo de registradores de contexto de execução arquiteturais (por exemplo,
RIP, RSP, RBP em x86_64), endereços de memória e dados de espaço de usuário
e de kernel de processos, conteúdo de vários MSRs arquiteturais que capturam
dados desta categoria.
Dados que pertencem à quarta categoria podem conter potencialmente dados confidenciais
do processo. Se as PMUs em alguns modos de monitoramento capturam valores de registradores
de contexto de execução ou dados da memória do processo, o acesso a esses modos de
monitoramento precisa ser ordenado e protegido adequadamente. Portanto, as operações de
monitoramento de desempenho e observabilidade do perf_events são objeto de gerenciamento
de controle de acesso de segurança [5]_ .
Controle de acesso do perf_events
---------------------------------
Para realizar verificações de segurança, a implementação do Linux divide os
processos em duas categorias [6]_ : a) processos privilegiados (cujo ID de
usuário efetivo é 0, chamados de superusuário ou root) e b) processos não
privilegiados (cujo UID efetivo é diferente de zero). Processos privilegiados
ignoram todas as verificações de permissão de segurança do kernel, de modo que
o monitoramento de desempenho do perf_events está totalmente disponível para
processos privilegiados sem restrições de acesso, escopo e recursos.
Processos não privilegiados estão sujeitos a uma verificação completa de permissão
de segurança com base nas credenciais do processo [5]_ (geralmente: UID efetivo,
GID efetivo e lista de grupos suplementares).
O Linux divide os privilégios tradicionalmente associados ao superusuário em
unidades distintas, conhecidas como capacidades (capabilities) [6]_ , que podem
ser habilitadas e desabilitadas independentemente por thread para processos e
arquivos de usuários não privilegiados.
Processos não privilegiados com a capacidade CAP_PERFMON habilitada são tratados
como processos privilegiados em relação às operações de monitoramento de
desempenho e observabilidade do perf_events, contornando, assim, as verificações
de permissões de *escopo* no kernel. A CAP_PERFMON implementa o princípio do menor
privilégio [13]_ (POSIX 1003.1e: 2.2.2.39) para operações de monitoramento de
desempenho e observabilidade no kernel e fornece uma abordagem segura para o
monitoramento de desempenho e observabilidade no sistema.
Por motivos de compatibilidade retroativa, o acesso às operações de monitoramento
e observabilidade do perf_events também é aberto para processos privilegiados com
CAP_SYS_ADMIN, mas o uso de CAP_SYS_ADMIN para casos de uso de monitoramento e
observabilidade seguros é desencorajado em relação à capacidade CAP_PERFMON.
Se os registros de auditoria do sistema [14]_ para um processo usando a API de
chamada de sistema perf_events contiverem registros de negação para a obtenção de
ambas as capacidades CAP_PERFMON e CAP_SYS_ADMIN, fornecer ao processo apenas a
capacidade CAP_PERFMON é recomendado como a abordagem segura preferida para resolver
o log duplo de negação de acesso relacionado ao uso de monitoramento de desempenho
e observabilidade.
Antes do Linux v5.9, processos não privilegiados que usavam a chamada de sistema
perf_events também estavam sujeitos à verificação do modo de acesso ptrace
PTRACE_MODE_READ_REALCREDS [7]_ , cujo resultado determina se o monitoramento é
permitido. Portanto, processos não privilegiados com a capacidade CAP_SYS_PTRACE
recebiam permissão efetiva para passar na verificação. A partir do Linux v5.9, a
capacidade CAP_SYS_PTRACE não é necessária e a CAP_PERFMON é suficiente para que
processos executem operações de monitoramento de desempenho e observabilidade.
Outras capacidades concedidas a processos não privilegiados podem efetivamente
permitir a captura de dados adicionais necessários para análises posteriores de
desempenho de processos monitorados ou do sistema. Por exemplo, a capacidade
CAP_SYSLOG permite a leitura de endereços de memória do espaço de kernel a partir
do arquivo /proc/kallsyms.
Grupos de usuários privilegiados do Perf
----------------------------------------
Mecanismos de capacidades, arquivos privilegiados desprovidos de capacidade
(capability-dumb) [6]_, ACLs de sistema de arquivos [10]_ e o utilitário
sudo [15]_ podem ser usados para criar grupos dedicados de usuários privilegiados
do Perf com permissão para executar monitoramento de desempenho e observabilidade
sem limites. As etapas a seguir podem ser seguidas para criar esses grupos de
usuários privilegiados do Perf.
1. Crie o grupo perf_users de usuários privilegiados do Perf, atribua o grupo
perf_users ao executável da ferramenta Perf e restrinja o acesso ao executável
para outros usuários no sistema que não estejam no grupo perf_users:
::
# groupadd perf_users
# ls -alhF
-rwxr-xr-x 2 root root 11M Oct 19 15:12 perf
# chgrp perf_users perf
# ls -alhF
-rwxr-xr-x 2 root perf_users 11M Oct 19 15:12 perf
# chmod o-rwx perf
# ls -alhF
-rwxr-x--- 2 root perf_users 11M Oct 19 15:12 perf
2. Atribua as capacidades necessárias ao arquivo executável da ferramenta Perf e
habilite os membros do grupo perf_users com privilégios de monitoramento e
observabilidade [6]_ :
::
# setcap "cap_perfmon,cap_sys_ptrace,cap_syslog=ep" perf
# setcap -v "cap_perfmon,cap_sys_ptrace,cap_syslog=ep" perf
perf: OK
# getcap perf
perf = cap_sys_ptrace,cap_syslog,cap_perfmon+ep
Se a libcap [16]_ instalada ainda não oferecer suporte a "cap_perfmon", use "38",
ou seja:
::
# setcap "38,cap_ipc_lock,cap_sys_ptrace,cap_syslog=ep" perf
Observe que você pode precisar incluir 'cap_ipc_lock' na combinação para
ferramentas como 'perf top'; alternativamente, use 'perf top -m N' para reduzir a
memória que ele usa para o buffer de anel (ring buffer) do perf; consulte a seção
de alocação de memória abaixo.
O uso de uma libcap sem suporte a CAP_PERFMON fará com que cap_get_flag(caps, 38,
CAP_EFFECTIVE, &val) falhe, o que fará com que o evento padrão seja 'cycles:u',
portanto, como solução alternativa, solicite explicitamente o evento 'cycles', ou seja:
::
# perf top -e cycles
Para obter amostras do kernel e do usuário com um binário do perf com apenas CAP_PERFMON.
Como resultado, os membros do grupo perf_users são capazes de conduzir
monitoramento de desempenho e observabilidade utilizando a funcionalidade do
executável da ferramenta Perf configurado que, ao ser executado, passa nas
verificações de escopo do subsistema perf_events.
Caso não seja possível atribuir as capacidades necessárias ao executável da
ferramenta Perf (por exemplo, o sistema de arquivos está montado com a opção
nosuid ou atributos estendidos não são suportados pelo sistema de arquivos), a
criação de um ambiente privilegiado por capacidades, naturalmente um shell, é
possível. O shell fornece aos processos herdados a CAP_PERFMON e outras
capacidades necessárias para que operações de monitoramento de desempenho e
observabilidade estejam disponíveis no ambiente sem limites. O acesso ao ambiente
pode ser aberto via utilitário sudo apenas para membros do grupo perf_users. Para
criar tal ambiente:
1. Crie um script shell que utilize o utilitário capsh [16]_ para atribuir a
CAP_PERFMON e outras capacidades necessárias no conjunto de capacidades
ambiente (ambient capability set) do processo do shell, travar os bits de
segurança do processo após habilitar os bits SECBIT_NO_SETUID_FIXUP,
SECBIT_NOROOT e SECBIT_NO_CAP_AMBIENT_RAISE e, em seguida, alterar a
identidade do processo para o chamador do script via sudo, que deve ser
essencialmente um membro do grupo perf_users:
::
# ls -alh /usr/local/bin/perf.shell
-rwxr-xr-x. 1 root root 83 Oct 13 23:57 /usr/local/bin/perf.shell
# cat /usr/local/bin/perf.shell
exec /usr/sbin/capsh --iab=^cap_perfmon --secbits=239 --user=$SUDO_USER -- -l
2. Estenda a política do sudo no arquivo /etc/sudoers com uma regra para o grupo
perf_users:
::
# grep perf_users /etc/sudoers
%perf_users ALL=/usr/local/bin/perf.shell
3. Verifique se os membros do grupo perf_users têm acesso ao shell privilegiado
e têm a CAP_PERFMON e outras capacidades necessárias habilitadas nos conjuntos
de capacidades permitidas (permitted), efetivas (effective) e ambiente (ambient)
de um processo herdado:
::
$ id
uid=1003(capsh_test) gid=1004(capsh_test) groups=1004(capsh_test),1000(perf_users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ sudo perf.shell
[sudo] password for capsh_test:
$ grep Cap /proc/self/status
CapInh: 0000004000000000
CapPrm: 0000004000000000
CapEff: 0000004000000000
CapBnd: 000000ffffffffff
CapAmb: 0000004000000000
$ capsh --decode=0000004000000000
0x0000004000000000=cap_perfmon
Como resultado, os membros do grupo perf_users têm acesso ao ambiente
privilegiado onde podem usar ferramentas que empregam APIs de monitoramento
de desempenho governadas pela capacidade Linux CAP_PERFMON.
Este gerenciamento específico de controle de acesso está disponível apenas para
processos em execução pelo superusuário ou root com as capacidades CAP_SETPCAP,
CAP_SETFCAP [6]_ .
Usuários não privilegiados
--------------------------
O controle de *escopo* e *acesso* do perf_events para processos não
privilegiados é governado pela configuração perf_event_paranoid [2]_ :
-1:
Não impõe restrições de *escopo* e *acesso* ao uso do monitoramento de
desempenho do perf_events. O limite de travamento perf_event_mlock_kb [2]_
por usuário e por CPU é ignorado ao alocar buffers de memória para armazenar
dados de desempenho. Este é o modo menos seguro, pois o *escopo* monitorado
permitido é maximizado e nenhum limite específico do perf_events é imposto
aos *recursos* alocados para o monitoramento de desempenho.
>=0:
O *escopo* inclui o monitoramento de desempenho por processo e em todo o
sistema, mas exclui o monitoramento de tracepoints brutos e tracepoints de
funções do ftrace. Eventos de CPU e do sistema ocorridos durante a execução
no espaço de usuário ou no espaço de kernel podem ser monitorados e capturados
para análise posterior. O limite de travamento perf_event_mlock_kb por usuário
e por CPU é imposto, mas ignorado para processos não privilegiados com a
capacidade CAP_IPC_LOCK [6]_ .
>=1:
O *escopo* inclui apenas o monitoramento de desempenho por processo e exclui
o monitoramento de desempenho em todo o sistema. Eventos de CPU e do sistema
ocorridos durante a execução no espaço de usuário ou no espaço de kernel podem
ser monitorados e capturados para análise posterior. O limite de travamento
perf_event_mlock_kb por usuário e por CPU é imposto, mas ignorado para
processos não privilegiados com a capacidade CAP_IPC_LOCK.
>=2:
O *escopo* inclui apenas o monitoramento de desempenho por processo. Eventos
de CPU e do sistema ocorridos durante a execução apenas no espaço de usuário
podem ser monitorados e capturados para análise posterior. O limite de
travamento perf_event_mlock_kb por usuário e por CPU é imposto, mas ignorado
para processos não privilegiados com a capacidade CAP_IPC_LOCK.
Controle de recursos
--------------------
Descritores de arquivo abertos
++++++++++++++++++++++++++++++
A API de chamada de sistema perf_events [2]_ aloca descritores de arquivo para cada
evento de PMU configurado. Descritores de arquivos abertos são um recurso contabilizado
por processo e governado pelo limite RLIMIT_NOFILE [11]_ (ulimit -n), que geralmente é
derivado do processo do shell de login. Ao configurar a coleta do Perf para uma longa
lista de eventos em um sistema de servidor grande, esse limite pode ser facilmente
atingido, impedindo a configuração de monitoramento necessária. O limite RLIMIT_NOFILE
pode ser aumentado por usuário modificando o conteúdo do arquivo limits.conf [12]_ .
Normalmente, uma sessão de amostragem do Perf (perf record) requer uma quantidade de
descritores de arquivos perf_event abertos que não seja inferior ao número de eventos
monitorados multiplicado pelo número de CPUs monitoradas.
Alocação de memória
+++++++++++++++++++
A quantidade de memória disponível para processos de usuário para captura de dados
de monitoramento de desempenho é governada pela configuração perf_event_mlock_kb [2]_ .
Esta configuração de recurso específica do perf_event define os limites gerais de
memória por CPU permitidos para mapeamento pelos processos de usuário para executar
o monitoramento de desempenho. A configuração essencialmente estende o limite
RLIMIT_MEMLOCK [11]_ , mas apenas para regiões de memória mapeadas especificamente
para a captura de eventos de desempenho monitorados e dados relacionados.
Por exemplo, se uma máquina tiver oito núcleos e o limite perf_event_mlock_kb estiver
definido como 516 KiB, então um processo de usuário receberá 516 KiB * 8 = 4128 KiB
de memória acima do limite RLIMIT_MEMLOCK (ulimit -l) para buffers mmap do perf_event.
Em particular, isso significa que, se o usuário desejar iniciar dois ou mais processos
de monitoramento de desempenho, ele deverá distribuir manualmente os 4128 KiB disponíveis
entre os processos de monitoramento, por exemplo, usando a opção do modo de gravação
--mmap-pages do Perf. Caso contrário, o primeiro processo de monitoramento de desempenho
iniciado alocará todos os 4128 KiB disponíveis e os outros processos falharão em prosseguir
devido à falta de memória.
As restrições de recursos RLIMIT_MEMLOCK e perf_event_mlock_kb são ignoradas para
processos com a capacidade CAP_IPC_LOCK. Assim, usuários privilegiados de
perf_events/Perf podem receber memória acima das restrições para fins de monitoramento
de desempenho de perf_events/Perf fornecendo a capacidade CAP_IPC_LOCK ao executável
do Perf.
Bibliografia
------------
.. [1] `<https://lwn.net/Articles/337493/>`_
.. [2] `<http://man7.org/linux/man-pages/man2/perf_event_open.2.html>`_
.. [3] `<http://web.eece.maine.edu/~vweaver/projects/perf_events/>`_
.. [4] `<https://perf.wiki.kernel.org/index.php/Main_Page>`_
.. [5] `<https://www.kernel.org/doc/html/latest/security/credentials.html>`_
.. [6] `<http://man7.org/linux/man-pages/man7/capabilities.7.html>`_
.. [7] `<http://man7.org/linux/man-pages/man2/ptrace.2.html>`_
.. [8] `<https://en.wikipedia.org/wiki/Hardware_performance_counter>`_
.. [9] `<https://en.wikipedia.org/wiki/Model-specific_register>`_
.. [10] `<http://man7.org/linux/man-pages/man5/acl.5.html>`_
.. [11] `<http://man7.org/linux/man-pages/man2/getrlimit.2.html>`_
.. [12] `<http://man7.org/linux/man-pages/man5/limits.conf.5.html>`_
.. [13] `<https://sites.google.com/site/fullycapable>`_
.. [14] `<http://man7.org/linux/man-pages/man8/auditd.8.html>`_
.. [15] `<https://man7.org/linux/man-pages/man8/sudo.8.html>`_
.. [16] `<https://git.kernel.org/pub/scm/libs/libcap/libcap.git/>`_

View File

@ -0,0 +1,108 @@
.. SPDX-License-Identifier: GPL-2.0
===========================
Documentação para /proc/sys
===========================
Copyright (c) 1998, 1999, Rik van Riel <riel@nl.linux.org>
------------------------------------------------------------------------------
'Por que', ouço você perguntar, 'alguém iria sequer _querer_ documentação
para esses arquivos sysctl? Se alguém realmente precisa, está tudo no
código-fonte...'
Bem, esta documentação foi escrita porque algumas pessoas ou não sabem
que precisam ajustar algo, ou porque não têm tempo ou conhecimento
para ler o código-fonte.
Além disso, os programadores que construíram o sysctl o fizeram para
ser realmente utilizado, e não apenas pela diversão de programá-lo :-)
------------------------------------------------------------------------------
Aviso legal:
Como de costume, há duas coisas principais a se considerar:
1. você recebe pelo que paga
2. é de graça
As consequências são que eu não garanto a exatidão deste
documento e, se você vier reclamar comigo sobre como você bagunçou seu
sistema por causa de uma documentação incorreta, não sentirei pena de você.
Eu posso até rir de você...
Mas é claro, se você _realmente_ conseguir bagunçar seu sistema usando
apenas as opções de sysctl utilizadas neste arquivo, eu gostaria de saber
disso. Não apenas para dar boas risadas, mas também para ter certeza de que
você é a última pessoa lendo o manual (RTFM) a fazer essa besteira.
Em resumo, envie suas sugestões, correções e/ou histórias de terror
por e-mail para: <riel@nl.linux.org>
Rik van Riel.
--------------------------------------------------------------
Introdução
==========
O sysctl é um meio de configurar determinados aspectos do kernel
em tempo de execução, e o diretório /proc/sys/ existe para que você
nem precise de ferramentas especiais para fazer isso!
Na verdade, são necessárias apenas quatro coisas para usar esses recursos
de configuração:
- um sistema Linux em execução
- acesso root
- bom senso (isso é especialmente difícil de encontrar hoje em dia)
- conhecimento sobre o que todos esses valores significam
Como um rápido 'ls /proc/sys' mostrará, o diretório consiste em
vários subdiretórios (dependentes de arquitetura?). Cada subdiretório
trata principalmente de uma parte do kernel, permitindo que você faça
a configuração parte por parte, ou apenas algumas 'modificações temáticas'.
Esta documentação é sobre:
=============== ===============================================================
abi/ domínios de execução e personalidades
<$ARCH> controles de ajuste para várias arquiteturas de CPU (ex.: csky, s390)
crypto/ subsistema criptográfico
debug/ recursos de depuração
dev/ informações específicas de dispositivos (ex.: dev/cdrom/info)
fs/ sistemas de arquivos específicos
ajustes de manipuladores de arquivos (filehandle), inode, dentry e cotas
binfmt_misc <Documentation/admin-guide/binfmt-misc.rst>
kernel/ informações globais / ajustes do kernel
coisas diversas
alguns controles específicos de arquitetura
coisas de segurança (LSM)
net/ coisas de rede; para documentação consulte:
<Documentation/networking/>
proc/ <vazio>
sunrpc/ SUN Remote Procedure Call (NFS)
user/ limites por namespace de usuário
vm/ ajustes de gerenciamento de memória
gerenciamento de buffers e cache
xen/ controles do hipervisor Xen
=============== ===============================================================
Estes são os subdiretórios que tenho no meu sistema ou que foram descobertos
pesquisando pelo código-fonte. Pode haver mais ou outros subdiretórios em
outra configuração. Se você encontrar outro diretório, eu realmente gostaria de
saber sobre ele :-)
Todolist:
* abi
* crypto
* debug
* fs
* kernel
* net
* sunrpc
* user
* vm
* xen

View File

@ -0,0 +1,195 @@
.. SPDX-License-Identifier: GPL-2.0
Regras sobre como acessar informações no sysfs
==============================================
O sysfs exportado pelo kernel expõe detalhes internos de implementação do
kernel e depende de estruturas e do leiaute internos do kernel. Há um consenso
entre os desenvolvedores do kernel de que o kernel Linux não fornece uma API
interna estável. Portanto, existem aspectos da interface do sysfs que podem
não ser estáveis entre lançamentos do kernel.
Para minimizar o risco de quebrar os usuários do sysfs — que, na maioria dos
casos, são aplicações de espaço de usuário de baixo nível — a cada novo
lançamento do kernel, os usuários do sysfs devem seguir algumas regras para usar
uma forma o mais abstrata possível de acessar esse sistema de arquivos. Os
programas udev e HAL atuais já implementam isso, e os usuários são incentivados
a se conectar, se possível, às abstrações que esses programas fornecem em vez de
acessar o sysfs diretamente.
Mas, se você realmente quer ou precisa acessar o sysfs diretamente, siga as
seguintes regras e, assim, seus programas deverão funcionar com versões
futuras da interface do sysfs.
- Não use a libsysfs
Ela faz suposições sobre o sysfs que não são verdadeiras. Sua API não
oferece nenhuma abstração; ela expõe todos os detalhes de implementação do
driver-core do kernel em sua própria API. Portanto, ela não é melhor do que
ler diretórios e abrir os próprios arquivos.
Além disso, ela não é mantida ativamente no sentido de refletir o
desenvolvimento atual do kernel. O objetivo de fornecer uma interface
estável para o sysfs falhou; ela causa mais problemas do que resolve. Ela
viola muitas das regras deste documento.
- sysfs está sempre em ``/sys``
Analisar ``/proc/mounts`` é perda de tempo. Outros pontos de montagem são um
bug de configuração do sistema que você não deve tentar contornar. Para
casos de teste, talvez ofereça suporte a uma variável de ambiente
``SYSFS_PATH`` para sobrescrever o comportamento da aplicação, mas nunca
tente procurar pelo sysfs. Nunca tente montá-lo, a menos que você seja um
script de inicialização inicial (early boot).
- Dispositivos são apenas "dispositivos"
Não existe algo como dispositivos de classe, de barramento, físicos,
interfaces e afins com os quais você possa contar no espaço de usuário.
Tudo é simplesmente um "dispositivo". Tipos como classe, barramento,
físico... são apenas detalhes de implementação do kernel que não devem ser
esperados por aplicações que procuram dispositivos no sysfs.
As propriedades de um dispositivo são:
- devpath (``/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0``)
- idêntico ao valor de DEVPATH no evento enviado pelo kernel na criação e
remoção do dispositivo
- a chave única para o dispositivo naquele momento
- o caminho do kernel para o diretório do dispositivo sem o ``/sys`` inicial,
e sempre começando com uma barra
- todos os elementos de um devpath devem ser diretórios reais. Links
simbólicos apontando para /sys/devices devem ser sempre resolvidos para o
seu alvo real e o caminho do alvo deve ser usado para acessar o dispositivo.
Dessa forma, o devpath para o dispositivo corresponde ao devpath do kernel
usado no momento do evento.
- usar ou expor valores de symlinks como elementos em uma string de devpath
é um bug na aplicação
- nome do kernel (``sda``, ``tty``, ``0000:00:1f.2``, ...)
- um nome de diretório, idêntico ao último elemento do devpath
- as aplicações precisam lidar com espaços e caracteres como ``!`` no
nome
- subsistema (``block``, ``tty``, ``pci``, ...)
- string simples, nunca um caminho ou um link
- recuperado através da leitura do link "subsystem" e usando apenas o
último elemento do caminho de destino
- driver (``tg3``, ``ata_piix``, ``uhci_hcd``)
- uma string simples, que pode conter espaços, nunca um caminho ou um
link
- é recuperado pela leitura do link "driver" e usando apenas o último
elemento do caminho de destino
- dispositivos que não possuem o link "driver" simplesmente não possuem um
driver; copiar o valor do driver no contexto de um dispositivo filho é
um bug na aplicação
- atributos
- os arquivos no diretório do dispositivo ou arquivos abaixo de subdiretórios
do mesmo diretório de dispositivo
- acessar atributos alcançados por um symlink apontando para outro dispositivo,
como o link "device", é um bug na aplicação
Tudo o mais é apenas um detalhe de implementação do driver-core do kernel
que não deve ser presumido como estável entre lançamentos do kernel.
- Propriedades de dispositivos pais nunca pertencem a um dispositivo filho.
Sempre olhe para os próprios dispositivos pais para determinar as propriedades
de contexto do dispositivo. Se o dispositivo ``eth0`` ou ``sda`` não tiver
um link "driver", então esse dispositivo não possui um driver. Seu valor é vazio.
Nunca copie nenhuma propriedade do dispositivo pai para um dispositivo filho.
As propriedades do dispositivo pai podem mudar dinamicamente sem qualquer aviso
para o dispositivo filho.
- Hierarquia em uma única árvore de dispositivos
Há apenas um lugar válido no sysfs onde a hierarquia pode ser examinada
e este é abaixo de: ``/sys/devices.``
Está planejado que todos os diretórios de dispositivos terminarão na árvore
abaixo deste diretório.
- Classificação por subsistema
Atualmente, existem três locais para classificação de dispositivos:
``/sys/block,`` ``/sys/class`` e ``/sys/bus.`` Está planejado que estes não
conterão diretórios de dispositivos em si, mas apenas listas planas de
symlinks apontando para a árvore unificada ``/sys/devices``.
Todos os três locais têm regras completamente diferentes sobre como acessar
informações de dispositivos. Está planejado fundir todos os três diretórios de
classificação em um único local em ``/sys/subsystem``, seguindo o leiaute dos
diretórios de barramentos. Todos os barramentos e classes, incluindo o
subsistema de blocos convertido, aparecerão lá.
Os dispositivos pertencentes a um subsistema criarão um symlink no diretório
"devices" em ``/sys/subsystem/<name>/devices``,
Se ``/sys/subsystem`` existir, ``/sys/bus``, ``/sys/class`` e ``/sys/block``
podem ser ignorados. Se ele não existir, você sempre terá que varrer todos os
três locais, já que o kernel é livre para mover um subsistema de um local para
o outro, desde que os dispositivos ainda sejam acessíveis pelo mesmo nome de
subsistema.
Presumir que ``/sys/class/<subsystem>`` e ``/sys/bus/<subsystem>``, ou
``/sys/block`` e ``/sys/class/block`` não são intercambiáveis é um bug na
aplicação.
- Bloco
O subsistema de blocos convertido em ``/sys/class/block`` ou
``/sys/subsystem/block`` conterá os links para discos e partições no mesmo
nível, nunca em uma hierarquia. Presumir que o subsistema de blocos contém
apenas discos e não dispositivos de partição na mesma lista plana é um bug
na aplicação.
- Link "device" e links <subsystem>:<kernel name>
Nunca dependa do link "device". O link "device" é uma solução alternativa
para o leiaute antigo, onde dispositivos de classe não são criados em
``/sys/devices/`` como os dispositivos de barramento. Se a resolução de links
de um diretório de dispositivo não terminar em ``/sys/devices/``, você pode
usar o link "device" para encontrar os dispositivos pais em ``/sys/devices/``;
esse é o único uso válido do link "device"; ele nunca deve aparecer em nenhum
caminho como um elemento. Presumir a existência do link "device" para um
dispositivo em ``/sys/devices/`` é um bug na aplicação.
Acessar ``/sys/class/net/eth0/device`` é um bug na aplicação.
Nunca dependa dos links específicos de classe de volta para o diretório
``/sys/class``. Esses links também são uma solução paliativa para o erro de
projeto no qual dispositivos de classe não são criados em ``/sys/devices.``
Se um diretório de dispositivo não contiver diretórios para dispositivos
filhos, esses links podem ser usados para encontrar os dispositivos filhos em
``/sys/class.`` Esse é o único uso válido desses links; eles nunca devem
aparecer em nenhum caminho como um elemento. Presumir a existência desses links
para dispositivos que são diretórios reais de dispositivos filhos na árvore
``/sys/devices`` é um bug na aplicação.
Está planejado remover todos esses links quando todos os diretórios de
dispositivos de classe residirem em ``/sys/devices.``
- A posição dos dispositivos ao longo da cadeia de dispositivos pode mudar.
Nunca dependa de uma posição específica do dispositivo pai no devpath,
ou da cadeia de dispositivos pais. O kernel é livre para inserir dispositivos
na cadeia. Você deve sempre requisitar o dispositivo pai que procura pelo
valor do seu subsistema. Você precisa percorrer a cadeia para cima até
encontrar o dispositivo correspondente ao subsistema esperado. Depender de
uma posição específica de um dispositivo pai ou expor caminhos relativos
usando ``../`` para acessar a cadeia de pais é um bug na aplicação.
- Ao ler e gravar arquivos de atributos de dispositivo do sysfs, evite a dependência
de códigos de erro específicos sempre que possível. Isso minimiza o acoplamento
com a implementação do tratamento de erros dentro do kernel.
Em geral, falhas ao ler ou gravar atributos de dispositivos no sysfs devem
propagar erros sempre que possível. Erros comuns incluem, mas não estão
limitados a:
``-EIO``: A operação de leitura ou gravação não é suportada, tipicamente
retornada pelo próprio sistema sysfs se o ponteiro de leitura ou gravação
for ``NULL``.
``-ENXIO``: A operação de leitura ou gravação falhou
Os códigos de erro não serão alterados sem um bom motivo, e caso uma alteração
nos códigos de erro resulte em quebra no espaço de usuário, ela será corrigida,
ou a alteração causadora será revertida.
As aplicações do espaço de usuário podem, no entanto, esperar que o formato e
o conteúdo dos arquivos de atributos permaneçam consistentes na ausência de uma
mudança no atributo de versão no contexto de um determinado atributo.

View File

@ -7,12 +7,16 @@ Dicas de depuração para desenvolvedores do Kernel Linux
Guias gerais
------------
.. toctree::
:maxdepth: 1
userspace_debugging_guide
Todolist:
* driver_development_debugging_guide
* gdb-kernel-debugging
* kgdb
* userspace_debugging_guide
Guias específicos de subsistemas
--------------------------------
@ -40,8 +44,8 @@ andamento?
Nesse caso, sua capacidade de depuração depende do suporte de depuração
embutido no kernel fornecido pela distribuição.
O :doc:`/process/debugging/userspace_debugging_guide` fornece uma breve visão
geral sobre uma variedade de ferramentas de depuração possíveis nessa situação.
O :doc:`userspace_debugging_guide` fornece uma breve visão geral sobre uma
variedade de ferramentas de depuração possíveis nessa situação.
Você pode verificar a capacidade do seu kernel, na maioria dos casos, olhando o
arquivo de configuração dentro do diretório /boot.

View File

@ -0,0 +1,297 @@
.. SPDX-License-Identifier: GPL-2.0
====================================================
Conselhos de depuração a partir do espaço de usuário
====================================================
Este documento fornece uma breve visão geral das ferramentas mais comuns
para depurar o kernel Linux a partir do espaço de usuário.
Para conselhos de depuração voltados a desenvolvedores de drivers, veja
:doc:`aqui </process/debugging/driver_development_debugging_guide>`.
Para conselhos gerais de depuração, veja o :doc:`documento de conselhos
gerais <index>`.
.. contents::
:depth: 3
As seções a seguir apresentam as ferramentas disponíveis.
Dynamic debug
-------------
Mecanismo para filtrar o que chega ao log do kernel, desabilitando ou
habilitando mensagens de log.
Pré-requisito: ``CONFIG_DYNAMIC_DEBUG``
O dynamic debug só consegue atuar sobre:
- pr_debug()
- dev_dbg()
- print_hex_dump_debug()
- print_hex_dump_bytes()
Por isso a utilidade dessa ferramenta é, até o momento, bastante limitada,
já que não há uma regra uniforme para adicionar prints de depuração ao
código-fonte, o que resulta em uma variedade de formas de implementar
esses prints.
Note também que a maioria das instruções de depuração é implementada como
uma variação de dprintk(), que precisa ser ativada por um parâmetro no
módulo correspondente; o dynamic debug não é capaz de fazer essa etapa por
você.
Eis um exemplo que habilita todos os pr_debug() disponíveis no arquivo::
$ alias ddcmd='echo $* > /proc/dynamic_debug/control'
$ ddcmd '-p; file v4l2-h264.c +p'
$ grep =p /proc/dynamic_debug/control
drivers/media/v4l2-core/v4l2-h264.c:372 [v4l2_h264]print_ref_list_b =p
"ref_pic_list_b%u (cur_poc %u%c) %s"
drivers/media/v4l2-core/v4l2-h264.c:333 [v4l2_h264]print_ref_list_p =p
"ref_pic_list_p (cur_poc %u%c) %s\n"
**Quando usar isto em vez do Ftrace?**
- Quando o código contém uma das instruções de print válidas (veja acima)
ou quando você adicionou várias instruções pr_debug() durante o
desenvolvimento
- Quando o tempo não é um problema, ou seja, se várias instruções
pr_debug() no código não causarem atrasos
- Quando você se importa mais em receber mensagens de log específicas do
que em rastrear o padrão de chamadas de uma função
Para a documentação completa, veja
:doc:`/admin-guide/dynamic-debug-howto`
Ftrace
------
Pré-requisito: ``CONFIG_DYNAMIC_FTRACE``
Esta ferramenta usa o sistema de arquivos tracefs para os arquivos de
controle e de saída. Esse sistema de arquivos é montado como um diretório
``tracing``, que pode ser encontrado em ``/sys/kernel/`` ou em
``/sys/debug/kernel/``.
Algumas das operações mais importantes para depuração são:
- Você pode fazer um rastreamento de função adicionando o nome da função
ao arquivo ``set_ftrace_filter`` (que aceita qualquer nome de função
encontrado no arquivo ``available_filter_functions``) ou pode
desabilitar funções específicas adicionando seus nomes ao arquivo
``set_ftrace_notrace`` (mais informações em:
:ref:`trace/ftrace:dynamic ftrace`).
- Para descobrir de onde partem as chamadas, você pode ativar a opção
``func_stack_trace`` em ``options/func_stack_trace``.
- Rastrear as funções filhas de uma chamada e exibir os valores de retorno
é possível adicionando a função desejada ao arquivo
``set_graph_function`` (requer a configuração ``FUNCTION_GRAPH_RETVAL``);
mais informações em
:ref:`trace/ftrace:dynamic ftrace with the function graph tracer`.
Para a documentação completa do Ftrace, veja :doc:`/trace/ftrace`
Você também pode rastrear eventos específicos :ref:`usando o rastreamento
de eventos <trace/events:2. using event tracing>`, que pode ser definido
conforme descrito aqui: :ref:`Criando um tracepoint customizado do Ftrace
<process/debugging/driver_development_debugging_guide:ftrace>`.
Para a documentação completa do rastreamento de eventos do Ftrace, veja
:doc:`/trace/events`
.. _pt_BR_read_ftrace_log:
Lendo o log do ftrace
~~~~~~~~~~~~~~~~~~~~~
O arquivo ``trace`` pode ser lido como qualquer outro arquivo (``cat``,
``tail``, ``head``, ``vim``, etc.); o tamanho do arquivo é limitado pelo
``buffer_size_kb`` (``echo 1000 > buffer_size_kb``). O
:ref:`trace/ftrace:trace_pipe` se comporta de forma semelhante ao arquivo
``trace``, mas sempre que você lê o arquivo o conteúdo é consumido.
Kernelshark
~~~~~~~~~~~
Uma interface gráfica para visualizar os rastreamentos em forma de gráfico
e de lista, a partir da saída da aplicação `trace-cmd
<https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/>`__.
Para a documentação completa, veja
`<https://kernelshark.org/Documentation.html>`__
Perf e alternativas
-------------------
As ferramentas mencionadas acima oferecem maneiras de inspecionar o código
do kernel, resultados, valores de variáveis, etc. Às vezes você precisa
primeiro descobrir onde olhar e, para esses casos, um conjunto de
ferramentas de acompanhamento de desempenho pode ajudar a delimitar o
problema.
Por que fazer uma análise de desempenho?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Uma análise de desempenho é um bom primeiro passo quando, entre outros
motivos:
- você não consegue definir o problema
- você não sabe onde ele ocorre
- o sistema em execução não deve ser interrompido, ou é um sistema remoto
no qual você não pode instalar um novo módulo/kernel
Como fazer uma análise simples com ferramentas do Linux?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Para iniciar uma análise de desempenho, você pode começar com as
ferramentas usuais, como:
- ``top`` / ``htop`` / ``atop`` (*obtenha uma visão geral da carga do
sistema, veja picos em processos específicos*)
- ``mpstat -P ALL`` (*observe a distribuição de carga entre as CPUs*)
- ``iostat -x`` (*observe a utilização e o desempenho dos dispositivos de
entrada e saída*)
- ``vmstat`` (*visão geral do uso de memória no sistema*)
- ``pidstat`` (*semelhante ao* ``vmstat`` *, mas por processo, para
restringir ao alvo*)
- ``strace -tp $PID`` (*uma vez que você conhece o processo, pode descobrir
como ele se comunica com o kernel*)
Isso deve ajudar a reduzir suficientemente as áreas a serem investigadas.
Indo mais fundo com o perf
~~~~~~~~~~~~~~~~~~~~~~~~~~
A ferramenta **perf** fornece uma série de métricas e eventos para
aprofundar a investigação dos problemas.
Pré-requisito: compilar ou instalar o perf no seu sistema
Coletar dados estatísticos ao procurar todos os arquivos que começam com
``gcc`` em ``/usr``::
# perf stat -d find /usr -name 'gcc*' | wc -l
Performance counter stats for 'find /usr -name gcc*':
1277.81 msec task-clock # 0.997 CPUs utilized
9 context-switches # 7.043 /sec
1 cpu-migrations # 0.783 /sec
704 page-faults # 550.943 /sec
766548897 cycles # 0.600 GHz (97.15%)
798285467 instructions # 1.04 insn per cycle (97.15%)
57582731 branches # 45.064 M/sec (2.85%)
3842573 branch-misses # 6.67% of all branches (97.15%)
281616097 L1-dcache-loads # 220.390 M/sec (97.15%)
4220975 L1-dcache-load-misses # 1.50% of all L1-dcache accesses (97.15%)
<not supported> LLC-loads
<not supported> LLC-load-misses
1.281746009 seconds time elapsed
0.508796000 seconds user
0.773209000 seconds sys
52
A disponibilidade de eventos e métricas depende do sistema em que você está
executando.
Para a documentação completa, veja
`<https://perf.wiki.kernel.org/index.php/Main_Page>`__
Perfetto
~~~~~~~~
Um conjunto de ferramentas para medir e analisar o desempenho de
aplicações e sistemas. Você pode usá-lo para:
* identificar gargalos
* otimizar código
* fazer o software rodar mais rápido e de forma mais eficiente.
**Qual é a diferença entre o perfetto e o perf?**
* o perf é uma ferramenta que faz parte do kernel Linux e é especializada
nele, com interface de linha de comando.
* o Perfetto é um conjunto multiplataforma de ferramentas para análise de
desempenho, estende suas funcionalidades ao espaço de usuário e oferece
uma interface web.
Para a documentação completa, veja `<https://perfetto.dev/docs/>`__
Ferramentas de análise de kernel panic
--------------------------------------
Para capturar o crash dump, use ``Kdump`` e ``Kexec``. Abaixo você
encontra alguns conselhos para analisar os dados.
Para a documentação completa, veja :doc:`/admin-guide/kdump/kdump`
Para encontrar a linha correspondente no código, você pode usar o
`faddr2line
<https://elixir.bootlin.com/linux/v6.11.6/source/scripts/faddr2line>`__;
note que é preciso habilitar ``CONFIG_DEBUG_INFO`` para que isso
funcione.
Uma alternativa ao ``faddr2line`` é o uso do ``objdump`` (e de suas
variantes para as diferentes plataformas, como
``aarch64-linux-gnu-objdump``). Tome esta linha como exemplo:
``[ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec]``.
Podemos encontrar a linha de código correspondente executando::
aarch64-linux-gnu-objdump -dS drivers/staging/media/rkvdec/rockchip-vdec.ko | grep rkvdec_device_run\>: -A 40
0000000000000ac8 <rkvdec_device_run>:
ac8: d503201f nop
acc: d503201f nop
{
ad0: d503233f paciasp
ad4: a9bd7bfd stp x29, x30, [sp, #-48]!
ad8: 910003fd mov x29, sp
adc: a90153f3 stp x19, x20, [sp, #16]
ae0: a9025bf5 stp x21, x22, [sp, #32]
const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
ae4: f9411814 ldr x20, [x0, #560]
struct rkvdec_dev *rkvdec = ctx->dev;
ae8: f9418015 ldr x21, [x0, #768]
if (WARN_ON(!desc))
aec: b4000654 cbz x20, bb4 <rkvdec_device_run+0xec>
ret = pm_runtime_resume_and_get(rkvdec->dev);
af0: f943d2b6 ldr x22, [x21, #1952]
ret = __pm_runtime_resume(dev, RPM_GET_PUT);
af4: aa0003f3 mov x19, x0
af8: 52800081 mov w1, #0x4 // #4
afc: aa1603e0 mov x0, x22
b00: 94000000 bl 0 <__pm_runtime_resume>
if (ret < 0) {
b04: 37f80340 tbnz w0, #31, b6c <rkvdec_device_run+0xa4>
dev_warn(rkvdec->dev, "Not good\n");
b08: f943d2a0 ldr x0, [x21, #1952]
b0c: 90000001 adrp x1, 0 <rkvdec_try_ctrl-0x8>
b10: 91000021 add x1, x1, #0x0
b14: 94000000 bl 0 <_dev_warn>
*bad = 1;
b18: d2800001 mov x1, #0x0 // #0
...
Ou seja, nesta linha do crash dump::
[ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec]
Posso tomar ``0x50`` como deslocamento, que devo somar ao endereço base
da função correspondente, que encontro nesta linha::
0000000000000ac8 <rkvdec_device_run>:
O resultado de ``0xac8 + 0x50 = 0xb18``
E quando procuro por esse endereço dentro da função, obtenho a seguinte
linha::
*bad = 1;
b18: d2800001 mov x1, #0x0
**Copyright** ©2024 : Collabora

View File

@ -357,7 +357,7 @@ extern __must_check int check_zeroed_user(const void __user *from, size_t size);
* struct).
*
* @ksize is just sizeof(*dst), and @usize should've been passed by userspace.
* The recommended usage is something like the following:
* The recommended usage is something like the following::
*
* SYSCALL_DEFINE2(foobar, const struct foo __user *, uarg, size_t, usize)
* {
@ -447,7 +447,7 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
* about data it does not.
*
* @ksize is just sizeof(*src), and @usize should've been passed by userspace.
* The recommended usage is something like the following:
* The recommended usage is something like the following::
*
* SYSCALL_DEFINE2(foobar, struct foo __user *, uarg, size_t, usize)
* {
@ -529,7 +529,7 @@ __copy_struct_generic_bounce_buffer(void *dst, size_t dstsize,
memcpy(dst, src, size);
}
/**
/*
* This is like copy_struct_from_user(), but the
* src buffer was already copied into a kernel
* bounce buffer, so it will never return -EFAULT.
@ -553,7 +553,7 @@ copy_struct_from_bounce_buffer(void *dst, size_t dstsize,
return 0;
}
/**
/*
* This is like copy_struct_to_user(), but the
* dst buffer is a kernel bounce buffer instead
* of a direct userspace buffer, so it will never return -EFAULT.
@ -770,7 +770,7 @@ static __always_inline void __scoped_user_rw_access_end(const void *p)
* If the user access function inside the scope requires a fault label, it
* can use @elbl or a different label outside the scope, which requires
* that user access which is implemented with ASM GOTO has been properly
* wrapped. See unsafe_get_user() for reference.
* wrapped. See unsafe_get_user() for reference::
*
* scoped_user_rw_access(ptr, efault) {
* unsafe_get_user(rval, &ptr->rval, efault);

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
#
# pylint: disable=R0903,R0912,R0913,R0914,R0917,C0301
# pylint: disable=R0903,R0912,R0913,R0914,R0915,R0917,C0301
"""
Install minimal supported requirements for different Sphinx versions
@ -11,40 +11,64 @@ and optionally test the build.
import argparse
import asyncio
import glob
import os.path
import shutil
import re
import sys
import time
import subprocess
# Minimal python version supported by the building system.
from textwrap import indent
PYTHON = os.path.basename(sys.executable)
MIN_PYTHON_SUBVER = 9 # Currently, Python 3.9 is the minimal supported version
min_python_bin = None
RE_VERSION = re.compile(r"python3\.\d+$")
for i in range(9, 13):
p = f"python3.{i}"
if shutil.which(p):
min_python_bin = p
break
if not min_python_bin:
min_python_bin = PYTHON
def get_min_python_bin(min_subver):
"""Get minimal python binary since 3.MIN_PYTHON_SUBVER"""
bins = set()
# Starting from 8.0, Python 3.9 is not supported anymore.
PYTHON_VER_CHANGES = {(8, 0, 0): PYTHON}
paths = os.environ.get("PATH", "").split(os.pathsep)
for d in paths:
for p in glob.glob(os.path.join(d, "python3.[0-9]*")):
if not RE_VERSION.search(p):
continue
ver = int(p.split(".")[1])
if ver < min_subver:
continue
if os.path.isfile(p) and os.access(p, os.X_OK):
bins.add(p)
if not bins:
return None
return sorted(bins, key=lambda x: (3, int(x.split(".")[1])))[0]
# Minimal python versions. Please notice that for 3.4.3, older python
# versions would work with Sphinx, but kernel doc build is not compatible
# with them anymore, due to Sphinx extensions and kernel-doc.
PYTHON_VER_CHANGES = {
(3, 4, 3): (3, MIN_PYTHON_SUBVER),
(8, 0, 0): (3, 10),
(8, 1, 0): (3, 11),
(9, 1, 0): (3, 12),
}
DEFAULT_VERSIONS_TO_TEST = [
(3, 4, 3), # Minimal supported version
(5, 3, 0), # CentOS Stream 9 / AlmaLinux 9
(6, 1, 1), # Debian 12
(7, 2, 1), # openSUSE Leap 15.6
(7, 2, 6), # Ubuntu 24.04 LTS
(7, 4, 7), # Ubuntu 24.10
(7, 3, 0), # openSUSE Tumbleweed
(8, 1, 3), # Fedora 42
(8, 2, 3) # Latest version - covers rolling distros
(3, 4, 3), # Minimal supported version
(5, 3, 0), # CentOS Stream 9 / AlmaLinux 9
(6, 1, 1), # Debian 12
(7, 2, 1), # openSUSE Leap 15.6
(7, 2, 6), # Ubuntu 24.04 LTS
(7, 4, 7), # Ubuntu 24.10
(7, 3, 0), # openSUSE Tumbleweed
(8, 1, 3), # Debian 13
(8, 2, 3), # Ubuntu 26.04 LTS / Fedora 44
(9, 1, 0), # Latest version
]
# Sphinx versions to be installed and their incremental requirements
@ -55,7 +79,6 @@ SPHINX_REQUIREMENTS = {
"alabaster": "0.7.12",
"babel": "2.8.0",
"certifi": "2020.6.20",
"docutils": "0.16",
"idna": "2.10",
"imagesize": "1.2.0",
"Jinja2": "2.11.2",
@ -89,7 +112,7 @@ SPHINX_REQUIREMENTS = {
"sphinxcontrib-applehelp": "1.0.4",
"sphinxcontrib-htmlhelp": "2.0.1",
"sphinxcontrib-serializinghtml": "1.1.5",
"urllib3": "2.0.0",
"urllib3": "2.0.2",
},
# Starting from here, ensure all docutils versions are covered with
@ -160,6 +183,10 @@ SPHINX_REQUIREMENTS = {
"PyYAML": "6.0.1",
"sphinxcontrib-serializinghtml": "1.1.9",
},
# from https://raw.githubusercontent.com/sphinx-doc/sphinx/v9.0.0/pyproject.toml
(9, 0, 0): {
"roman-numerals": "1.0.0",
},
}
@ -173,7 +200,8 @@ class AsyncCommands:
self.output = None
self.fp = fp
def log(self, out, verbose, is_info=True):
def log(self, out, verbose=True, is_info=True):
"""Ancillary routine to output a message"""
out = out.removesuffix('\n')
if verbose:
@ -202,7 +230,6 @@ class AsyncCommands:
async def run(self, cmd, capture_output=False, check=False,
env=None, verbose=True):
"""
Execute an arbitrary command, handling errors.
@ -301,8 +328,8 @@ class SphinxVenv:
# Pip install succeeded. Write requirements file
if args.req_file:
with open(req_file, "w", encoding="utf-8") as fp:
fp.write(result.stdout)
with open(req_file, "w", encoding="utf-8") as fout:
fout.write(result.stdout)
if args.build:
start_time = time.time()
@ -354,7 +381,7 @@ class SphinxVenv:
"""
if args.log:
fp = open(args.log, "w", encoding="utf-8")
fp = open(args.log, "w", encoding="utf-8") # pylint: disable=R1732
if not args.verbose:
args.verbose = False
else:
@ -362,8 +389,19 @@ class SphinxVenv:
if not args.verbose:
args.verbose = True
cmd = AsyncCommands(fp)
cur_requirements = {}
python_bin = min_python_bin
python_bin = get_min_python_bin(MIN_PYTHON_SUBVER)
if not python_bin:
python_bin = os.path.basename(sys.executable)
python_ver = tuple(sys.version_info[:2])
if python_ver < (3, MIN_PYTHON_SUBVER):
sys.exit(f"Python {python_ver[0]}.{python_ver[1]} is too old.")
else:
ver = int(python_bin.split(".")[1])
python_ver = tuple([3, ver])
vers = set(SPHINX_REQUIREMENTS.keys()) | set(args.versions)
@ -372,8 +410,14 @@ class SphinxVenv:
new_reqs = SPHINX_REQUIREMENTS[cur_ver]
cur_requirements.update(new_reqs)
if cur_ver in PYTHON_VER_CHANGES: # pylint: disable=R1715
python_bin = PYTHON_VER_CHANGES[cur_ver]
if cur_ver in PYTHON_VER_CHANGES:
new_ver = PYTHON_VER_CHANGES[cur_ver]
if python_ver < new_ver:
python_bin = get_min_python_bin(new_ver[1])
if not python_bin:
cmd.log(f"Can't check {cur_ver}: {python_bin} not found.")
break
if cur_ver not in args.versions:
continue
@ -390,7 +434,6 @@ class SphinxVenv:
python_bin)
if args.build:
cmd = AsyncCommands(fp)
cmd.log("\nSummary:", verbose=True)
for ver, elapsed_time in sorted(self.built_time.items()):
cmd.log(f"\tSphinx {ver} elapsed time: {elapsed_time}",
@ -399,15 +442,15 @@ class SphinxVenv:
if fp:
fp.close()
def parse_version(ver_str):
"""Convert a version string into a tuple."""
return tuple(map(int, ver_str.split(".")))
DEFAULT_VERS = " - "
DEFAULT_VERS += "\n - ".join(map(lambda v: f"{v[0]}.{v[1]}.{v[2]}",
DEFAULT_VERSIONS_TO_TEST))
DEFAULT_VERS = indent("\n".join(map(lambda v: f"{v[0]}.{v[1]}.{v[2]}",
DEFAULT_VERSIONS_TO_TEST)), " - ")
SCRIPT = os.path.relpath(__file__)
@ -452,6 +495,7 @@ MAKE_TARGETS = [
"xmldocs",
]
async def main():
"""Main program"""
@ -499,8 +543,6 @@ async def main():
if not args.make_args:
args.make_args = []
sphinx_versions = sorted(list(SPHINX_REQUIREMENTS.keys()))
if args.full:
args.versions += list(SPHINX_REQUIREMENTS.keys())

View File

@ -45,6 +45,7 @@ class CTransforms:
(CMatch("DECLARE_HASHTABLE"), r"unsigned long \1[1 << ((\2) - 1)]"),
(CMatch("DECLARE_KFIFO"), r"\2 *\1"),
(CMatch("DECLARE_KFIFO_PTR"), r"\2 *\1"),
(CMatch("DECLARE_KHOSER_PTR"), r"\2 \1"),
(CMatch("DECLARE_PIDS"), r"struct pid *\1[(\2) + 1]"),
(CMatch("(?:__)?DECLARE_FLEX_ARRAY"), r"\1 \2[]"),
(CMatch("DEFINE_DMA_UNMAP_ADDR"), r"dma_addr_t \1"),