O que pode fazer com que a passagem de init = / path / to / program para o kernel não inicie o programa como init?

13

Estou tentando depurar um script de inicialização em um sistema Linux; Estou tentando passar init=/bin/sh para o kernel para fazer com que ele inicie sh sem iniciar init , para que eu possa executar a sequência init manualmente.

O que eu descobri é que o kernel está iniciando init de qualquer maneira. Durante a inicialização, uma das mensagens printk é a linha de comando, e isso mostra que a linha está sendo configurada corretamente; Além disso, posso afetar outras coisas usando a linha de comando do kernel. Eu verifiquei se o caminho existe; isso acontece.

Este é um sistema busybox, e o init é um link simbólico para o busybox; Então, para ter certeza de que o busybox não faz mágica estranha quando seu PID é 1, eu também tentei rodar um programa que não seja o busybox como init; isso não funcionou também. Parece que não importa o que eu faça, o init é executado.

O que poderia estar causando esse comportamento?

    
por Shawn J. Goff 30.01.2012 / 22:14

4 respostas

3

Olhando para o código-fonte do kernel Linux, vejo que se o arquivo / init existir, o kernel sempre tentará executá-lo assumindo que está executando uma inicialização com ramdisk. Verifique o seu sistema para ver se o / init existe, se isso acontecer, então provavelmente esse é o seu problema.

    
por 31.01.2012 / 03:35
7

shitanigans initrd

Se você estiver usando initrd ou initramfs, tenha em mente o seguinte:

  • rdinit= é usado em vez de init=

  • se rdinit= não for fornecido, os caminhos padrão tentados serão: /sbin/init , /etc/init , /bin/init e /bin/sh , mas não /init

    Quando não estiver usando initrd, /init é o primeiro caminho tentado, seguido pelos outros.

v4.15 RTFS: tudo está contido no arquivo link .

Primeiro, aprendemos que:

  • execute_comand é o que for passado para: init=
  • ramdisk_execute_command é o que for passado para: rdinit=

como pode ser visto em:

static int __init init_setup(char *str)
{
    unsigned int i;

    execute_command = str;
    /*
    * In case LILO is going to boot us with default command line,
    * it prepends "auto" before the whole cmdline which makes
    * the shell think it should execute a script with such name.
    * So we ignore all arguments entered _before_ init=... [MJ]
    */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("init=", init_setup);

static int __init rdinit_setup(char *str)
{
    unsigned int i;

    ramdisk_execute_command = str;
    /* See "auto" comment in init_setup */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("rdinit=", rdinit_setup);

onde __setup é uma maneira mágica de manipular os parâmetros da linha de comando.

start_kernel , o "ponto de entrada" do kernel, chama rest_init , que "chama" kernel_init em um encadeamento:

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

Então, kernel_init faz:

static int __ref kernel_init(void *unused)
{
    int ret;

    kernel_init_freeable();

    [...]

    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return 0;
        pr_err("Failed to execute %s (error %d)\n",
            ramdisk_execute_command, ret);
    }

    [...]

    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return 0;
        panic("Requested init %s failed (error %d).",
            execute_command, ret);
    }
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    panic("No working init found.  Try passing init= option to kernel. "
        "See Linux Documentation/admin-guide/init.rst for guidance.");
}

e kernel_init_freeable :

static noinline void __init kernel_init_freeable(void)
{

    [...]

    if (!ramdisk_execute_command)
        ramdisk_execute_command = "/init";

    if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
        ramdisk_execute_command = NULL;
        prepare_namespace();
    }

TODO: entenda sys_access .

Observe também que existem outras diferenças entre inits de memória ram e inits não ram, e. manipulação de console: Diferença na execução do init com initramfs embutidos vs. externos?

    
por 16.03.2018 / 13:37
4

Em

link

Eu encontrei:

When debugging a normal root filesystem, it's nice to be able to boot with "init=/bin/sh". The initramfs equivalent is "rdinit=/bin/sh", and it's just as useful.

Então provavelmente tente ridinit = / bin / sh

    
por 29.08.2013 / 16:40
0

Você pode customizar seu kernel Linux e recompilá-lo. Para o kernel 4.9, Edite a função "kernel_init" em init / main.c e tente executar a seguinte linha primeiro:

try_to_run_init_process("/bin/sh")

Além disso, pode ser causado pelos parâmetros do kernel passados pelo BootLoader.

    
por 07.06.2017 / 09:54

Tags