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.