67 votes

Que se passe-t-il si je lance accidentellement la commande "chmod -R" sur des répertoires système (/, /etc, ...) ?

J'ai accidentellement lancé

sudo chmod 755 -R /

au lieu de

sudo chmod 755 -R ./

Je l'ai arrêté après quelques secondes, mais maintenant il y a quelques problèmes tels que

sudo: must be setuid root

Comment puis-je rétablir les autorisations ?

68voto

ulidtko Points 5283

En bref : vous ne pouvez pas, réinstallez votre système.

Je veux dire que les permissions Posix sont utilisées et qu'on s'y fie énormément ; il y a une multitude d'endroits dans le système de fichiers où de mauvaises permissions pourraient casser le système d'exploitation (drapeaux SUID) ou pire, le rendre vulnérable du point de vue de la sécurité ( /etc/ssh/ssh_host_rsa_key ) alors qu'il semble fonctionner correctement.

Il est donc difficile d'effectuer correctement une telle récupération. Mlle une chose - et vous le foutez en l'air. Vous déjà a bousillé votre sudo chmod (si c'est votre ami plutôt que vous, elle pourrait aussi bien apprendre une leçon de Linux) - et c'est un ordre très simple. Une récupération correcte demanderait beaucoup plus de commandes et beaucoup plus de vigilance. Même si vous utilisez le script de quelqu'un.

Alors, faites-moi confiance, réinstallez. C'est un pari sûr et une garantie de ne pas avoir de problèmes.


Enfin, quelques conseils pertinents ici.

Premièrement : les réinstallations seront moins douloureuses si vous mettre en place votre /home sur une partition séparée la prochaine fois. En fait, ce sera un jeu d'enfant.

Deuxièmement, envisagez de faire la science folle de Linux dans un machine virtuelle comme la VirtualBox, et faites vos snapshots.

Troisièmement : chmod -R . travaux. Un point par lui-même . est un nom de répertoire valide. Il n'y a pas vraiment besoin d'ajouter cette barre oblique. Vous auriez pu éviter le risque catastrophique de sauter le point en entier ;
simple chmod: missing operand after ‘755’ VS un système en ruine.

28voto

mataal Points 318

J'ai écrit et j'utilise depuis plusieurs années un couple de scripts Ruby scripts pour rsync les autorisations et la propriété. script get-filesystem-acl collecte toutes les informations en parcourant récursivement tous les fichiers et les place toutes dans le fichier .acl . script .acl-restore lira .acl et appliquer tous les chown et chmod 's.

Vous pouvez exécuter get-filesystem-acl sur une installation similaire d'Ubuntu, puis copier sur les .acl sur votre boîte avec chmod, mettez .acl y .acl-restore dans /, et exécutez .acl-restore .

Vous aurez besoin d'avoir la racine pour réparer votre sudo comme l'a suggéré Marco Ceppi.

Je peux générer et vous donner le .acl pour mon Ubuntu.

get-filesystem-acl

#!/usr/bin/ruby

RM   = "/bin/rm"
SORT = "/usr/bin/sort"
TMP  = "/tmp/get_acl_#{Time.now.to_i}_#{rand * 899 + 100}"

require 'find'

IGNORE = [".git"]

def numeric2human(m)
  return sprintf("%c%c%c%c%c%c%c%c%c",
            (m & 0400 == 0 ? ?- : ?r),
            (m & 0200 == 0 ? ?- : ?w),
            (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
                             (m & 04000 == 0 ? ?x : ?s)),
            (m & 0040 == 0 ? ?- : ?r),
            (m & 0020 == 0 ? ?- : ?w),
            (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
                             (m & 02000 == 0 ? ?x : ?s)),
            (m & 0004 == 0 ? ?- : ?r),
            (m & 0002 == 0 ? ?- : ?w),
            (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
                             (m & 01000 == 0 ? ?x : ?t)))
end

File.open(TMP, "w") do |acl_file|

  # TODO: Instead of the current dir, find the .git dir, which could be
  #       the same or outside of the current dir
  Find.find(".") do |path|

    next if IGNORE.collect {|ig| !!(path[2..-1] =~ /\A#{ig}/)}.include? true
    next if File.symlink?(path)

    stat = File.lstat(path)
    group_id = stat.gid
    rules    = "#{type}#{numeric2human(stat.mode)}" 

    acl_file.puts "#{path} #{rules} #{owner_id} #{group_id}"
  end
end

`#{SORT} #{TMP} > .acl`
`#{RM}   #{TMP}`

.acl-restore

#!/usr/bin/ruby

# This script will only work with .acl_ids

# Restore from...
FROM  = ".acl"

MKDIR = "/bin/mkdir"
CHMOD = "/bin/chmod"
CHOWN = "/bin/chown"
known_content_missing = false

def numeric2human(m)
  return sprintf("%c%c%c%c%c%c%c%c%c",
            (m & 0400 == 0 ? ?- : ?r),
            (m & 0200 == 0 ? ?- : ?w),
            (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
                             (m & 04000 == 0 ? ?x : ?s)),
            (m & 0040 == 0 ? ?- : ?r),
            (m & 0020 == 0 ? ?- : ?w),
            (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
                             (m & 02000 == 0 ? ?x : ?s)),
            (m & 0004 == 0 ? ?- : ?r),
            (m & 0002 == 0 ? ?- : ?w),
            (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
                             (m & 01000 == 0 ? ?x : ?t)))
end

def human2chmod(mode)
  raise unless mode =~ /([r-][w-][xtsTS-])([r-][w-][xtsTS-])([r-][w-][xtsTS-])/
  triple = [$1, $2, $3]
  u,g,o = triple.collect do |i|
    i.sub('s', 'sx').sub('t', 'tx').downcase.gsub('-', '')
  end

  return "u=#{u},g=#{g},o=#{o}" 
end

File.open(FROM).each do |acl|
  raise unless acl =~ /\A(([^ ]*? )+)([^ ]+) ([^ ]+) ([^ ]+)\Z/
  path, rules, owner_id, group_id = $1, $3, $4, $5
  path = path.strip
  owner_id = owner_id.to_i
  group_id = group_id.to_i

  if !File.exists?(path) and !File.symlink?(path)
    if rules =~ /\Ad/
      STDERR.puts "Restoring a missing directory: #{path}"
      STDERR.puts "Probably it was an empty directory. Git goes not track them."
      `#{MKDIR} -p '#{path}'` # Creating the any parents
    else
      known_content_missing = true
      STDERR.puts "ERROR: ACL is listed but the file is missing: #{path}"
      next
    end
  end

  s = File.lstat(path)
  t = s.ftype[0..0].sub('f', '-') # Single character for the file type
                                  # But a "-" istead of "f"

  # Actual, but not neccesarely Desired 
  actual_rules    = "#{t}#{numeric2human(s.mode)}"
  actual_owner_id = s.uid 
  actual_group_id = s.gid 

  unless [actual_rules, actual_owner_id, actual_group_id] ==
    [rules, owner_id, group_id]

    chmod_argument = human2chmod(rules)

    # Debug
    #p chmod_argument
    #p s.mode

    ## Verbose
    puts path
    puts "Wrong: #{[actual_rules, actual_owner_id, actual_group_id].inspect}"
    puts "Fixed: #{[rules, owner_id, group_id].inspect}"
    `#{CHMOD} #{chmod_argument} '#{path}'`

    #puts
  end

end

if known_content_missing
  STDERR.puts "-" * 80 
  STDERR.puts "Some files that are listed in #{FROM.inspect} are missing in " +
              "the current directory."
  STDERR.puts
  STDERR.puts "Is #{FROM.inspect} outdated?"
  STDERR.puts "(Try retrograding the current directory to an earlier version)"
  STDERR.puts
  STDERR.puts "Or is the current directory incomplete?"
  STDERR.puts "(Try to recover the current directory)"
  STDERR.puts "-" * 80 
end

14voto

Redbaron Points 523

En bref : vous pouvez. Vous devrez monter le système de fichiers à partir d'un Live CD et commencer à inverser les permissions aux endroits appropriés. Au minimum, pour récupérer sudo, vous devez exécuter les commandes suivantes sudo chmod u+s /usr/bin/sudo dans la session LiveCD - cela corrigera le problème de l'utilisateur root setuid.

Cependant, il serait probablement plus facile de simplement réinstaller le système.

4voto

Adam Byrtek Points 9538

J'essaierais de réinstaller tous les paquets avec apt-get install --reinstall en utilisant éventuellement la sortie de dpkg --get-selections | grep install pour en obtenir la liste.

4voto

blade19899 Points 25776

D'accord, je n'ai pas testé ceci (donc utilisez à vos risques et périls), mais cela pourrait fonctionner. Je testerai ceci dans une machine virtuelle quand j'en aurai l'occasion :

Tout d'abord, dans un système qui fonctionne encore, j'ai fait ce qui suit pour obtenir toutes les permissions de fichiers dans une liste, en sautant le bouton /home/ répertoire :

sudo find / -not -path /home -printf "%m:%p\0" > /tmp/fileper.log

Cela imprimera les permissions et le nom de chaque fichier ou répertoire sur le système, suivi d'un message \0 (ceci est nécessaire plus tard pour traiter les noms de fichiers bizarres tels que ceux contenant des nouvelles lignes).

Ensuite, sur un système où les autorisations de fichiers ont été compromises :

while IFS=: read -r -d '' perm file; do  
    chmod "$perm" "$file"
done < /tmp/fileper.log 

Ceci va lire chaque ligne de fileper.log en sauvegardant les permissions comme $perm et le nom du fichier comme $file puis définira les permissions du fichier (ou du répertoire) en fonction de ce qui a été indiqué dans la commande fileper.log


Quelques éléments à noter ici :

  • Pendant la sortie vers le fichier : /tmp/fileper.log vous pourriez énumérer les paramètres personnalisés, les proc, etc.
  • vous pourriez ne pas pouvoir démarrer, ou exécuter des commandes,

Ce que je vous suggère, c'est de démarrer un LiveCD avec la version de Linux que vous avez sur votre disque, d'exécuter la commande, de modifier le chemin vers l'endroit où vous avez monté le disque local, et d'exécuter la deuxième commande !


J'ai testé que lorsque je démarre à partir d'un CD/USB Ubuntu, je peux choisir de ne pas formater le disque, ce qui signifie qu'il remplacera tout ce qui se trouve dans le dossier de l'utilisateur. / répertoire, MAIS sauter le /home/ répertoire. Cela signifie que vos utilisateurs auront la configuration d'apps/DATA (Musique, Vidéo, Documents) toujours intacte. Et en remplaçant les fichiers système, le chmod est réglé sur le bon numéro.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X