Eu estendi o patch mencionado antes para verificar uma lista de dispositivos de bloco somente leitura configurados pela linha de comando de inicialização.
/*
* Block write and discard commands going to a read-only device.
* We do this because kernel drivers often lack necessary checks
* and send write/discard commands to read-only block devices.
*/
if (unlikely((bio->bi_rw & (REQ_WRITE | REQ_WRITE_SAME | REQ_DISCARD))
&& (bdev_read_only(bio->bi_bdev) || bdev_check_readonly_boot_param(bio->bi_bdev->bd_inode->i_rdev)))) {
pr_warn("unexpected %s command to %s blocked\n",
(bio->bi_rw & REQ_DISCARD) ? "discard" : "write",
bdevname(bio->bi_bdev, b));
goto end_io;
}
Este é o patch original estendido para verificar o parâmetro de inicialização com esta função:
extern dev_t READONLY_DEV[];
static inline int bdev_check_readonly_boot_param(dev_t bd)
{
dev_t *dev = READONLY_DEV;
while (*dev) {
if (*dev == bd) return 1;
dev++;
}
return 0;
}
No do_mounts.c
, adicionei isto:
static char __initdata saved_readonly_dev[64]; dev_t READONLY_DEV[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static int __init readonly_bdev_setup(char *line) { strlcpy(saved_readonly_dev, line, sizeof(saved_readonly_dev)); return 1; } __setup("forcero=", readonly_bdev_setup); /* * Setup list with read-only devices */ void __init setup_readonly_bdev(void) { int i = 0; char *dev_name, *readonly_dev; if (saved_readonly_dev[0]) { readonly_dev = saved_readonly_dev; do { dev_name = strsep(&readonly_dev, ","); if (dev_name) { READONLY_DEV[i] = name_to_dev_t(dev_name); if (READONLY_DEV[i]) { i++; printk(KERN_NOTICE "Set %s to read-only.\n",dev_name); } else printk(KERN_WARNING "Error setting read-only: Could not identify block-device '%s'\n",dev_name); } } while (dev_name); } }
Além disso, no main.c
na função kernel_init_freeable
eu adicionei uma linha para chamar minha função (a função é declarada em init.h
):
if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { ramdisk_execute_command = NULL; prepare_namespace(); } setup_readonly_bdev();
Agora você pode inicializar o kernel com o argumento de linha de comando forcero=8:16,8:17
e ele bloqueará todas as chamadas de gravação para esses dispositivos. /dev/sdb
não funciona para mim, a função kernel não pode resolver um dev_t
-id disso.
Note que o kernel não sabe que o dispositivo é somente de leitura, você pode escrever nele e até mesmo o dd não vai te informar nenhum problema, mas se você olhar no kern.log
, você verá muitos erros de I / O então. Se você excluir um arquivo na partição somente leitura em nemo
(o gerenciador de arquivos padrão da GUI do Cinnamon), ele será removido, mas você pressionará F5 e voltará.
Também é importante: o bloqueio de /dev/sda
não bloqueará automaticamente dispositivos como /dev/sda1
, você precisa listar todos os dispositivos de bloco. Mas isso significa que você pode proteger o setor de inicialização / tabela de partição enquanto algumas partições são graváveis.
Esse patch com certeza não atende aos padrões de qualidade de código do kernel a serem mesclados, ficaria muito feliz se alguém pudesse limpá-lo / melhorá-lo ou me dizer o que devo fazer.