Comment puis-je retourner un bit dans un fichier?

35

Je veux endommager intentionnellement un fichier afin de tester les affirmations selon lesquelles btrfs peut se soigner lui-même . L'article parle de supprimer le système de fichiers, d'endommager une photo en "retournant" un bit, puis en le remontant. Dans les systèmes de fichiers plus anciens, cela serait simplement corrompu mais il est supposé se corriger lui-même dans btrfs. En théorie, cela a du sens mais je veux vraiment le tester.

Le problème est que l'article n'explique pas comment faire cela.
Comment pourrais-je changer un bit dans une partie très spécifique d'un système de fichiers?

Je devrais également souligner que cela doit être fait sur un système de fichiers hors connexion afin que btrfs ne considère pas mon écriture comme intentionnelle.

Edit: Bien que la question (et la discussion) parlent beaucoup de btrfs, j'aimerais savoir s'il existe des méthodes indépendantes du système de fichiers pour implémenter ce type de corruption (afin de pouvoir la comparer à travers différents types de RAID / contrôleurs / etc).

Oli
la source
@Dan, je veux dire que si j'édite directement le fichier, btrfs (ou n'importe quel système de fichiers) comptera comme une écriture valide. Cela ne donnerait pas la corruption que je cherche.
Oli
S'agit-il d'un système de fichiers test (par exemple, le contenu vous importe peu ou la restauration à partir d'une sauvegarde vous convient parfaitement? De plus, utilisez-vous une seule partition btrfs sur un seul lecteur ou une seule partition au-dessus d'une grappe RAID? , ou une autre configuration?
Darth Android
1
Si btrfs prend en charge les bons ioctls (vous ne le savez pas vraiment), vous pouvez utiliser filefrag -vpour savoir exactement où se trouve un fichier.
derobert
3
@Oli Je suppose que vous trouverez un public plus intéressé sur U & L, à la fois en termes de votes et de réponses. en plus, ça .
Strugee
1
Tirez sur un rayon cosmique au bon endroit.
smcg

Réponses:

20

Je ne suis pas un expert, mais le btrfs-progspackage inclut en fait un outil spécialement conçu à cet effet, bien que vous deviez peut-être créer à partir des sources. Dans tous les cas, une fois que vous avez installé ou construit btrfs-progs, vous devriez pouvoir utiliser l'outil btrfs-corrupt-block, qui est utilisé par les développeurs de btrfs pour tester le système de fichiers.

Maintenant, comme je l'ai dit, je n'ai pas eu beaucoup de temps pour jouer avec btrfs, alors je ne connais pas l'utilisation exacte de cet outil. Mais avec cela, vous devriez pouvoir corrompre un système de fichiers hors connexion, qui sera corrigé à la lecture du fichier corrompu (en supposant que vous ayez configuré RAID ou quelque chose de telle sorte qu'il y ait une autre copie à utiliser).

combattant
la source
2
Super trouvaille! En supposant que cela btrfs-corrupt-blocksoit écrit comme un véritable test et non une "astuce" par les développeurs de btrfs, cela devrait correspondre exactement à la facture.
Allquixotic
@allquixotic Si vous voulez en savoir plus sur btrfs, vous trouverez une excellente conférence dans linux.conf.au 2012 . comme je l'ai dit, btrfs-corrupt-blockest utilisé par les développeurs, donc ce ne serait pas très utile si c'était un truc :)
14h14
3
@allquixotic C'est la beauté de l'open source: vous pouvez regarder le code source de btrfs et le vérifier! Bien sûr, cela ne sera pas une tâche facile, mais si vous le voulez vraiment, vous pouvez le faire.
Bakuriu
@ Bakuriu, je suis tout à fait au courant. Je n’ai jamais sérieusement douté que ce btrfs-corrupt-blockn’était pas un test sincère, puisqu’il serait découvert très rapidement par quelqu'un cherchant à pointer à la source et utilisé comme PR négatif contre Oracle (du moins; ainsi que tout autre développeur / contributeur de btrfs). C'était juste un commentaire improvisé.
Allquixotic
Je me demande si l'OP (@Oli) veut corrompre un bloc (c'est-à-dire la structure du système de fichiers) ou un fichier (c'est-à-dire le contenu d'un fichier ??) ... le premier, pas le dernier? [Comment un système de fichiers peut-il savoir quel bit a été retourné dans un fichier? une sorte de CRC?]. Cette réponse est probablement dans le droit, donc +1. [mais cela peut changer plus qu'un "seul bit"? ou changer quelque chose qui peut être guéri plus facilement qu'un passage aléatoire "n'importe où"?]
Olivier Dulac
16
  1. Obtenir la valeur d'un seul secteur sur le bloc (par exemple /dev/sda1) avec un décalage d'un million de secteurs (à titre d'exemple):

    sudo dd if=/dev/sda1 of=/root/mysector bs=512 count=1 skip=1M
    

    Ce décalage arbitraire de 1M * 512 octets, choisi au hasard, sert simplement à vous assurer que vous n’êtes pas dans la partie métadonnées du système de fichiers et qu’il s’agit bien d’un secteur contenant des données.

  2. Éditez les données de secteur brutes en modifiant le contenu avec un éditeur hexadécimal. Voir par exemple Besoin d'un bon éditeur hexadécimal pour Linux .

  3. Remettez le secteur sur le lecteur avec les arguments ifet ofinversés:

    sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    
Gertvdijk
la source
2
Cela ne l'aidera pas à tester à moins que le millionième bloc ne fasse en réalité partie d'un fichier. Comment peut-il rechercher sur quel bloc un fichier particulier commence?
Darth Android
3
C'est tellement presque là. Si vous pouvez verrouiller la commande dd sur la position exacte du fichier, c'est probablement la meilleure façon de procéder.
Oli
@ Oli Oui, je sais comment faire cela pour la famille de systèmes de fichiers Ext, mais je n'ai pas beaucoup d'expérience avec btrfs. Laissez-moi voir si je peux trouver un moyen.
gertvdijk
2
@Oli: vous pouvez simplement avoir une boucle, sortie sortie bloc par bloc (c'est-à-dire, comme ci-dessus, mais "skip = N", N étant dans 1..max) jusqu'à ce que vous puissiez afficher une ligne du fichier que vous souhaitez modifier. [essayez de générer une ligne qui ne se produira nulle part ailleurs ... par exemple, prenez-la à partir d'un générateur de mot de passe, et assez longtemps?]. Ensuite, vous éditez ce bloc particulier. remonter, tester si la modification a été annulée (ce dont je doute, voir mon commentaire dans la réponse en haut ... il semble y avoir une confusion entre les données du fichier (= contenu) et la structure même du système de fichiers (= comment les fichiers et leur contenu sont organisés )?)
Olivier Dulac
16

@Oli - Salut, je suis Jim Salter, le gars qui a écrit cet article. Je travaillais avec une machine virtuelle, ce qui simplifiait les choses. Ce que j'ai fait est démarré avec un fichier JPEG et ouvert dans un éditeur hexadécimal. Celui que j'ai utilisé était Bless, que vous pouvez installer dans Ubuntu avec une simple installation d’apt-get bless .

Après avoir ouvert le fichier JPEG dans Bless, j’ai jeté plusieurs fois la page vers le bas pour bien entrer dans la "viande" du JPEG, puis juste mis en évidence une cinquantaine de octets de données, que je copiais et collais dans un éditeur de texte cas, gEdit). Cela m'a donné quelque chose à rechercher.

Maintenant, j'ai enregistré le JPEG dans chaque tableau de la VM. Le stockage derrière les baies était constitué d’une série de fichiers .qcow2. Une fois le fichier JPEG sauvegardé dans les tableaux, je pouvais charger dans Bless les fichiers .qcow2 associés à chaque tableau et les rechercher - ils n'étaient pas très volumineux, n'étant rien d'autre que du JPEG et des métadonnées - pour ce modèle de cinquante octets. J'avais mis en évidence et copié à partir du JPEG. Voilà, j'avais le bloc à corrompre! À ce stade, je pouvais simplement éditer manuellement des octets individuels du fichier JPEG stocké sur le disque virtuel de la machine virtuelle à l'aide de Bless - et, ce qui est important, le faire exactement de la même manière sur chaque baie.

Le seul inconvénient est que, dans le cas de la matrice RAID5 testée dans l'article, je devais m'assurer que j'avais édité la copie réelle des données de la bande, et non la parité de la bande elle-même - il s'agissait d'une petite image sur une sinon, tableau vide, il n'y a donc aucune donnée dans le bloc FOLLOWING dans la bande, ce qui fait que le bloc de parité contient les données non modifiées du bloc de données. Si j'avais édité accidentellement le bloc de parité au lieu du bloc de données, l'image serait restée inchangée.

Une dernière remarque - vous n’AVEZ PAS BESOIN de machines virtuelles pour le faire - vous pouvez faire les mêmes choses de la même manière avec du métal nu; ce serait simplement plus pénible parce que vous auriez besoin de travailler avec des lecteurs bruts entiers plutôt qu'avec de jolis petits fichiers .qcow2, et de tirer les lecteurs et de les placer dans un autre ordinateur, ou démarrez dans un environnement réel (ou simplement alternatif) pour vous compliquer la vie. (J'ai testé la récupération de données de ZFS exactement de cette manière, mais sur de véritables machines nues, il y a sept ans lorsque je me suis intéressé aux systèmes de fichiers next-gen.)

J'espère que cela t'aides!

Jim Salter
la source
4

Vous pouvez essayer un petit programme qui fonctionnera sur le fichier ouvert.FIBMAP ioctl(2)

En effectuant une recherche rapide sur le Web, j'ai trouvé cet article de blog http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html détaillant comment procéder, il vous donnera même un lien. à un exemple de programme que vous pouvez compiler et exécuter vous-même.

$ git clone git://kernel.ubuntu.com/cking/debug-code
$ cd debug-code/block-mapper-fibmap
$ make
$ sudo ./fibmap /path/to/your/image-file.jpg

C'est exactement la façon dont hdparm --fibmap(mentionné par @falconer) est implémentée.

Après avoir trouvé les numéros de bloc, vous pouvez utiliser ddgongfu pour modifier le fichier, comme @gertvdijk. Ou peut-être pourriez-vous simplement modifier le fibmap.cprogramme ci-dessus pour qu'il effectue le retournement, écrivant directement dans le fichier de périphérique en contournant la couche de système de fichiers (trois paramètres du programme: 1. le chemin du fichier, 2. le fichier de périphérique contenant le fichier système, décalage et bit que vous souhaitez modifier).

( Avertissement: je n'ai pas testé et ne peux pas garantir que FIBMAP ioctl(2)cela fonctionnera pour un fichier dans un périphérique de bouclage ou un système de fichiers btrfs, mais je m'attendrais fortement à ce qu'il le soit. Je suppose que hdparm je vérifierai le type de périphérique avant d'exécuter le ioctl(2)sur le fichier et est donc échouer.)

FooF
la source
3
sudo hdparm --fibmap /PATH/TO/FILE

vous donnera les LBA où se trouve le fichier. Après cela, vous pouvez utiliser la réponse de @gertvdijk.

fauconnier
la source
Malheureusement, cela ne semble pas fonctionner. Il crache un 0,39: device not found in /devC'est soit parce que c'est btrfs ou (plus probablement) parce que je l'utilise sur des fichiers en boucle. Je vais essayer de faire cela avec une "bonne" VM.
Oli
@ Oli Hmm. Je pensais que cela hdparmfonctionnait sur tous les systèmes de fichiers, mais ce n’est peut-être pas le cas.
Fauconnier