注目の記事

Amazon Linux 2 で「rm -rf /*」を実行してみた

よい子(大人を含む)はマネしないでね
2021.07.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

噂の最狂コマンドを実行してみたくなった

みなさんはrm -rf /*でOSを破壊しようとしたことはありますか? 流石の私もないです。

rm -rf /*は、OSのrootディレクトリ配下を確認なしで全て削除すると言われる 最狂コマンドです。

rm -rf /という似たコマンドもありますが、こちらは、–no-preserve-rootというオプションを付けなければ、削除処理が実行されない安全仕様になっています。そのため、rm -rf /*の方がより凶悪仕様とも言えます。

今回は無性にOSが壊れゆく様を見たいと思ったので、Amazon Linux 2上でrm -rf /*を実行してみて、どこまで壊れるのか確認してみます。

また、rm -rf /*実行後、緊急モードなどから復旧できそうなら、復旧にもチャレンジしてみます。

いきなりまとめ

  • rm -rf /*はやっぱり キケン。遊び半分でしてはいけない。
  • rm -rf /*実行後は、EC2インスタンスを再起動してもOSが立ち上がってこない
  • 緊急モードで起動しようとしても、/bootも削除されており、何もできない
  • rm -rf /*を実行しても全てのディレクトリ、ファイルが消える訳ではない
    • しかし、/bin/sbinなどバイナリファイルは削除されているので、ほとんどのコマンドが実行できない
    • 一方で、cdechoなどのシェルに組み込まれているビルトインコマンドは実行可能
  • もしrm -rf /*を実行してしまったら、素直にAMIからリストアしよう

「rm -rf /*」を実行するための準備

Amazon Linux 2で、rm -rf /*を実行する際は、sshで接続してではなく、シリアルコンソールで接続して行います。

仮にsshで接続してrm -rf /*を実行したとしても、sshのプロセスも削除され、OSが壊れゆく様を最期まで見届けれない可能性があります。

そのため、シリアルコンソールでEC2インスタンスに接続して、どんなログが出力されるのかを眺めていきたいと思います。

シリアルコンソールでEC2インスタンスに接続する方法は、以下記事をご参照ください。

シリアルコンソールでEC2インスタンスに接続すると、以下のような画面になります。

「rm -rf /*」を実行する

それでは、rm -rf /*を実行していきます。

/procや、/sys/moduleなどを削除しようとしてOperation not permittedと表示されながらも、実行して20分ほどで削除が完了しました。Failed to create new system journal: No such file or directoryと表示されていることから、ジャーナルすら削除されています。

「さてさて、どんなディレクトリは残っているのかな」と状況か確認しようと、lswhichを叩いてみてもそんなコマンドはない!と一蹴されてしまいます。最狂コマンドは伊達じゃないですね。

少し話は脱線しますが、cdビルトインコマンドであるため、rm -rf /*の影響を受けず、実行できています。(今回はcdを実行しても指定したディレクトリがないため、ディレクトリが存在しないとのメッセージが表示されます)

コマンドの種類を確認するためにtype cdを実行すると、ビルトインコマンドを示すcd is a shell builtinと表示されます。

ビルトインコマンドの一覧はhelpで確認できます。helpを実行すると、These shell commands are defined internally.とビルトインコマンドの一覧を確認できます。

> help
GNU bash, version 4.2.46(2)-release (x86_64-koji-linux-gnu)
These shell commands are defined internally.  Type `help' to see this list.
Type `help name' to find out more about the function `name'.
Use `info bash' to find out more about the shell in general.
Use `man -k' or `info' to find out more about commands not in this list.

A star (*) next to a name means that the command is disabled.

 job_spec [&]                                         history [-c] [-d offset] [n] or history -anrw [fi>
 (( expression ))                                     if COMMANDS; then COMMANDS; [ elif COMMANDS; then>
 . filename [arguments]                               jobs [-lnprs] [jobspec ...] or jobs -x command [a>
 :                                                    kill [-s sigspec | -n signum | -sigspec] pid | jo>
 [ arg... ]                                           let arg [arg ...]
 [[ expression ]]                                     local [option] name[=value] ...
 alias [-p] [name[=value] ... ]                       logout [n]
 bg [job_spec ...]                                    mapfile [-n count] [-O origin] [-s count] [-t] [->
 bind [-lpvsPVS] [-m keymap] [-f filename] [-q name>  popd [-n] [+N | -N]
 break [n]                                            printf [-v var] format [arguments]
 builtin [shell-builtin [arg ...]]                    pushd [-n] [+N | -N | dir]
 caller [expr]                                        pwd [-LP]
 case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]>  read [-ers] [-a array] [-d delim] [-i text] [-n n>
 cd [-L|[-P [-e]]] [dir]                              readarray [-n count] [-O origin] [-s count] [-t] >
 command [-pVv] command [arg ...]                     readonly [-aAf] [name[=value] ...] or readonly -p>
 compgen [-abcdefgjksuv] [-o option]  [-A action] [>  return [n]
 complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [>  select NAME [in WORDS ... ;] do COMMANDS; done
 compopt [-o|+o option] [-DE] [name ...]              set [-abefhkmnptuvxBCHP] [-o option-name] [--] [a>
 continue [n]                                         shift [n]
 coproc [NAME] command [redirections]                 shopt [-pqsu] [-o] [optname ...]
 declare [-aAfFgilrtux] [-p] [name[=value] ...]       source filename [arguments]
 dirs [-clpv] [+N] [-N]                               suspend [-f]
 disown [-h] [-ar] [jobspec ...]                      test [expr]
 echo [-neE] [arg ...]                                time [-p] pipeline
 enable [-a] [-dnps] [-f filename] [name ...]         times
 eval [arg ...]                                       trap [-lp] [[arg] signal_spec ...]
 exec [-cl] [-a name] [command [arguments ...]] [re>  true
 exit [n]                                             type [-afptP] name [name ...]
 export [-fn] [name[=value] ...] or export -p         typeset [-aAfFgilrtux] [-p] name[=value] ...
 false                                                ulimit [-SHacdefilmnpqrstuvx] [limit]
 fc [-e ename] [-lnr] [first] [last] or fc -s [pat=>  umask [-p] [-S] [mode]
 fg [job_spec]                                        unalias [-a] name [name ...]
 for NAME [in WORDS ... ] ; do COMMANDS; done         unset [-f] [-v] [name ...]
 for (( exp1; exp2; exp3 )); do COMMANDS; done        until COMMANDS; do COMMANDS; done
 function name { COMMANDS ; } or name () { COMMANDS>  variables - Names and meanings of some shell vari>
 getopts optstring name [arg]                         wait [id]
 hash [-lr] [-p pathname] [-dt] [name ...]            while COMMANDS; do COMMANDS; done
 help [-dms] [pattern ...]                            { COMMANDS ; }

これらビルトインコマンドは、シェル自体にコマンドが組み込まれているため、/bin/sbinにバイナリファイルがなくても実行できます。

なお、helpに出力されなかったコマンドを確認してみましたが、いずれも/usr/bin配下にバイナリファイルがある外部コマンドであることが分かります。

> type ls
ls is hashed (/usr/bin/ls)

> type cat
cat is hashed (/usr/bin/cat)

> type grep
grep is /usr/bin/grep

> type find
find is /usr/bin/find

> type cp
cp is /usr/bin/cp

> type mkdir
mkdir is /usr/bin/mkdir

> type tar
tar is /usr/bin/tar

> type yum
yum is /usr/bin/yum

> type which
which is hashed (/usr/bin/which)

脱線ここまで。

次に、rm -rf /*を実行した後にEC2インスタンスを再起動すると何か状況が変わるのかと思い、マネージメントコンソールからEC2インスタンスを再起動してみました。

再起動後、再度シリアルコンソールでEC2インスタンスに接続しました。すると、どうでしょう。どんなキーを叩いても反応しません。これには白旗です。

また、再起動後のEC2インスタンスをマネージメントコンソールから確認すると、以下のように インスタンスステータスのチェック に失敗していました。これはおそらく、ネットワークアダプターの設定周りも削除されてしまったからだと推測します。

「rm -rf /*」されたEBSボリュームを別のEC2インスタンスにアタッチして削除状態を確認してみる

rm -rf /* 実行後にどのようなディレクトリが消されずに残っているのか無性に気になりました。

どうしても確認したかったので、rm -rf /*されたEBSボリュームをデタッチして、別のEC2インスタンスにアタッチして確認してみます。

まず、rm -rf /*されたEBSボリュームをEC2インスタンスからデタッチします。

確認のウィンドウが表示されるので、デタッチするをクリックします。

デタッチしたEBSボリュームのステータスがavailableになることを確認します。

デタッチしたEBSボリュームを新規に作成したEC2インスタンスにアタッチします。

EBSボリュームのアタッチを行うと、rm -rf /*されたEBSボリュームのステータスがin-useになることを確認します。

新規に作成したEC2インスタンスにsshで接続して、fdisk -lでEBSボリュームがアタッチされているか確認します。

以下のようにOSから見て2つのディスクが認識されていますね。ハイライトした箇所のディスクがrm -rf /*されたEBSボリュームです。

> sudo  fdisk -l
Disk /dev/nvme0n1: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 8BDD20F1-855B-496D-AB49-4A93A0028D62

Device           Start      End  Sectors Size Type
/dev/nvme0n1p1    4096 16777182 16773087   8G Linux filesystem
/dev/nvme0n1p128  2048     4095     2048   1M BIOS boot

Partition table entries are not in disk order.


Disk /dev/nvme1n1: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 8BDD20F1-855B-496D-AB49-4A93A0028D62

Device           Start      End  Sectors Size Type
/dev/nvme1n1p1    4096 16777182 16773087   8G Linux filesystem
/dev/nvme1n1p128  2048     4095     2048   1M BIOS boot

Partition table entries are not in disk order.

ここで、「いざマウント!!」という気持ちは山々ですが、上述のfdisk -lの結果を確認すると、どちらのディスクもUUIDが同じです。

同じUUIDを持つ2つのファイルシステムを普通にマウントしようとすると、mount: <マウントポイント>: wrong fs type, bad option, bad superblock on /dev/nvme1n1p1, missing codepage or helper program, or other error.といったエラーを出力し、マウントできません。

そのため、以下記事で紹介している通り、UUIDの重複を無視するをオプション(-o nouuid)を指定してマウントします。

マウント及び、マウントした結果は以下の通りです。

# rm -rf /* されたEBSボリューム /dev/nvme1n1p1 を /mnt に xfs でマウント
> sudo mount -t xfs -o nouuid /dev/nvme1n1p1 /mnt

# マウントされていることを確認
# /dev/nvme1n1p1 が /mbt に xfs でマウントされていることが確認できる
> mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,size=479204k,nr_inodes=119801,mode=755)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
/dev/nvme0n1p1 on / type xfs (rw,noatime,attr2,inode64,noquota)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=9069)
mqueue on /dev/mqueue type mqueue (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=97996k,mode=700)
/dev/nvme1n1p1 on /mnt type xfs (rw,relatime,nouuid,attr2,inode64,noquota)

# df コマンドでも確認
> df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  468M     0  468M   0% /dev
tmpfs          tmpfs     479M     0  479M   0% /dev/shm
tmpfs          tmpfs     479M  416K  479M   1% /run
tmpfs          tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1 xfs       8.0G  1.5G  6.6G  18% /
tmpfs          tmpfs      96M     0   96M   0% /run/user/0
/dev/nvme1n1p1 xfs       8.0G   41M  8.0G   1% /mnt

それでは、rm -rf /*されたEBSボリュームの中身を確認していきます。

treeをインストールして、EBSボリュームをマウントした/mntディレクトリをツリー状に表示します。

# tree のインストール
> sudo yum install -y tree

> cd /mnt
> sudo tree
.
├── dev
│   ├── console
│   ├── fd -> /proc/self/fd
│   ├── null
│   ├── pts
│   ├── random
│   ├── stderr -> fd/2
│   ├── stdin -> fd/0
│   ├── stdout -> fd/1
│   ├── urandom
│   └── zero
├── proc
├── run
│   └── lock
│       └── lvm
├── sys
└── var
    └── lib
        └── nfs
            └── rpc_pipefs

12 directories, 8 files

/dev/nullなどの擬似デバイスファイルや、/dev/stdinなどの標準入出力、/var/lib/nfs/rpc_pipefs、その他ディレクトリの残骸がある程度で、ほとんどのディレクトリ、ファイルが削除されていることが確認できますね。

緊急モードで起動してみる

緊急モードとは

ここまでOSを破壊しておいて何ですが、ここから復旧できるものなら復旧させてあげたいと思いました。

正常にOSが起動しない時にすることといったら、レスキューモード(シングルユーザーモード)、もしくは緊急モードでの起動です。

レスキューモード(シングルユーザーモード)と緊急モードの違いは起動するサービスやボリュームのマウント方法に違いがあります。

緊急モードで起動した際に起動するサービスは緊急モード用のシェルとジャーナルのみです。また、ボリュームも読み取り専用でマウントされます。

緊急モードでの起動は、こちらのAWS公式ドキュメントで紹介されている通り、カーネルが破損していた場合や、/etc/fstabで誤った設定をしていた場合に発生します。

緊急モードで起動するために、わざわざカーネルを壊したり、/etc/fstabの設定方法を変更したりすると、「rm -rf /*を使ってOSを破壊する」という本題から外れそうなので、手動で緊急モードで起動します。

シリアルコンソールを使用してEC2インスタンスに接続できるようになったことで、以下AWS公式ドキュメントの通り、GRUBでカーネルの起動方法を選択することができます。シリアルコンソール最高です。

GNU GRUB (GNU GRand Unified Bootloader の略。一般に GRUB と呼ばれます) は、ほとんどの Linux オペレーティングシステムのデフォルトのブートローダーです。GRUB メニューから、起動先のカーネルを選択したり、メニューエントリを変更してカーネルの起動方法を変更したりできます。これは、障害が発生したインスタンスをトラブルシューティングする際に役立ちます。

GRUB メニューは、ブートプロセス中に表示されます。通常の SSH ではメニューにアクセスできませんが、EC2 シリアルコンソールからアクセスできます。

Prerequisites

GRUB を設定して使用するには、シリアルコンソールへのアクセスを許可する必要があります。詳細については、「EC2 シリアルコンソールへのアクセスを設定する」を参照してください。

GRUB を使用して Linux インスタンスをトラブルシューティングする

緊急モードで起動するための準備

上述のAWS公式ドキュメントで紹介されている手順を参考に、まず緊急モードで起動するための準備を行います。

rm -rf /*を実行したEC2インスタンスはめちゃくちゃな状態になってしまったので、綺麗な環境で設定するために新しくEC2インスタンスを作成します。

新規にEC2インスタンスを作成した後、sshやSSMセッションマネージャーで作成したEC2インスタンスに接続します。

その後、/etc/default/grubを以下のように追加及び、編集をします。

# デフォルトエントリー用のコマンドライン引数
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0"

# 起動時の待ち時間(秒数)
# 1秒以内に何か入力しない場合、デフォルトのカーネルで立ち上がる
GRUB_TIMEOUT=1

# リカバリーモードのエントリーを作成しない
GRUB_DISABLE_RECOVERY="true"

# GRUBへの入出力端末に "console" と "serial" を指定
GRUB_TERMINAL="console serial"

# シリアルコンソール用のコマンドライン引数
# シリアルコンソールの速度を設定
GRUB_SERIAL_COMMAND="serial --speed=115200"

/etc/default/grubの追加及び、編集後、以下コマンドでGRUBの設定ファイルであるgrub.cfgを生成します。

> sudo grub2-mkconfig -o /boot/grub2/grub.cfg

緊急モードの起動確認

それでは試しに緊急モードで起動してみます。

まず、シリアルコンソールでEC2インスタンスに接続します。

その後、次のコマンドを実行して、EC2インスタンスを再起動します。

> boot

再起動時に以下のようなGRUBメニューが表示されます。/etc/default/grubGRUB_TIMEOUTで設定した秒数以内に任意のキーを押してブートプロセスを停止させます。

GRUBメニューで、矢印キーを使用して起動先のカーネル(Amazon Linux 2)を選択し、キーボードの e を押します。すると、以下のような画面が表示されます。

起動カーネルを指定している行の末尾に以下のようにemergencyを追加します。レスキューモード(シングルユーザーモード)で起動する場合は、末尾にsingleを追加します。

emergency追加後、Ctrl+Xを入力することで緊急モードで起動します。ターミナルに以下のようなログが流れ、緊急モードで起動したとの内容が表示されます。rootユーザーのパスワードを入力してログインします。

ログイン後、起動しているサービスと、ボリュームのマウント状態を確認してみます。

以下の通り、各種コマンドを実行して確認してみました。

# 起動中のサービス一覧を表示
# 緊急モード用のシェルとジャーナルのサービスのみ起動
> systemctl list-units --type service
UNIT                     LOAD   ACTIVE SUB     DESCRIPTION
emergency.service        loaded active running Emergency Shell
systemd-journald.service loaded active running Journal Service

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

2 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

# network.service のステータスを表示
# network.service は起動していない
# そのため、sshやSSMセッションマネージャーで緊急モードのEC2インスタンスに接続することはできない
> systemctl status network.service
● network.service - LSB: Bring up/down networking
   Loaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)

# ボリュームのマウント状態を表示
# "/" が ro (Read Only)でマウントされていることが確認できる
> mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,size=479204k,nr_inodes=119801,mode=755)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/sy
stemd-cgroups-agent,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
/dev/nvme0n1p1 on / type xfs (ro,relatime,attr2,inode64,noquota)

参考までに、レスキューモードで起動した場合とどのような違いがあるのか気になったため、レスキューモードで起動した後に同様のコマンドを実行してみました。

以下の通り、起動しているサービスの数に大きな違いがあります。また、緊急モードでは読み込み専用だった/も読み書き可能な状態でマウントされています。

# 起動中のサービス一覧を表示
# 緊急モードの用に、レスキューモード用のシェルとジャーナルのサービスのみ起動しているのではなく、様々なサービスが起動している
> systemctl list-units --type service
UNIT                         LOAD   ACTIVE SUB     DESCRIPTION
dbus.service                 loaded active running D-Bus System Message Bus
ec2net-ifup@eth0.service     loaded active exited  Enable elastic network interf
kmod-static-nodes.service    loaded active exited  Create list of required stati
lvm2-lvmetad.service         loaded active running LVM2 metadata daemon
lvm2-monitor.service         loaded active exited  Monitoring of LVM2 mirrors, s
rescue.service               loaded active running Rescue Shell
rhel-dmesg.service           loaded active exited  Dump dmesg to /var/log/dmesg
rhel-domainname.service      loaded active exited  Read and set NIS domainname f
rhel-readonly.service        loaded active exited  Configure read-only root supp
systemd-fsck-root.service    loaded active exited  File System Check on Root Dev
systemd-journal-flush.service loaded active exited  Flush Journal to Persistent 
systemd-journald.service     loaded active running Journal Service
systemd-modules-load.service loaded active exited  Load Kernel Modules
systemd-random-seed.service  loaded active exited  Load/Save Random Seed
systemd-remount-fs.service   loaded active exited  Remount Root and Kernel File 
systemd-sysctl.service       loaded active exited  Apply Kernel Variables
systemd-tmpfiles-setup-dev.service loaded active exited  Create Static Device No
systemd-tmpfiles-setup.service loaded active exited  Create Volatile Files and D
systemd-udev-settle.service  loaded active exited  udev Wait for Complete Device
systemd-udev-trigger.service loaded active exited  udev Coldplug all Devices
systemd-udevd.service        loaded active running udev Kernel Device Manager
systemd-update-utmp.service  loaded active exited  Update UTMP about System Boot
systemd-vconsole-setup.service loaded active exited  Setup Virtual Console

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

23 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

# network.service のステータスを表示
# レスキューモードでも network.service は変わらず起動していない
> systemctl status network
● network.service - LSB: Bring up/down networking
   Loaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)
     
# ボリュームのマウント状態を表示
# "/" が rw (Read Write)でマウントされていることが確認できる
>  mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,size=479204k,nr_inodes=119801,mode=755)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/s
ystemd-cgroups-agent,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
/dev/nvme0n1p1 on / type xfs (rw,noatime,attr2,inode64,noquota)
mqueue on /dev/mqueue type mqueue (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=21,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=9018)

緊急モード及び、レスキューモードから抜ける際は、systemctl defaultもしくはexitを入力するか、rebootでOSを再起動します。

systemctl defaultを入力した結果は以下の通りです。cloud-initや、SSMエージェントが実行されていることが確認できます。

> systemctl default
[  526.667763] systemd-fsck[1187]: /usr/sbin/fsck.xfs: XFS file system.
[  526.687594] systemd-journald[1125]: Received request to flush runtime journal from PID 1
[  526.723142] ena 0000:00:05.0: Elastic Network Adapter (ENA) v2.5.0g
[  526.736030] ena 0000:00:05.0: ENA device version: 0.10
[  526.771001] ena 0000:00:05.0: ENA controller version: 0.0.1 implementation version 1
[  526.780548] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input4
[  526.790897] ACPI: Power Button [PWRF]
[  526.790977] input: ImPS/2 Generic Wheel Mouse as /devices/platform/i8042/serio1/input/input3
[  526.870224] input: Sleep Button as /devices/LNXSYSTM:00/LNXSLPBN:00/input/input5
[  526.884172] ACPI: Sleep Button [SLPF]
G[  527.016023] ena 0000:00:05.0: LLQ is not supported Fallback to host mode policy.
[  527.030306] mousedev: PS/2 mouse device common for all mice
[  527.037255] ena 0000:00:05.0: Elastic Network Adapter (ENA) found at mem febf4000, mac addr 02:13:dd:43:53:31
[  527.105188] AVX2 version of gcm_enc/dec engaged.
[  527.108761] AES CTR mode by8 optimization enabled
[  527.129800] alg: No test for pcbc(aes) (pcbc-aes-aesni)
[  527.227349] device-mapper: uevent: version 1.0.3
[  527.231129] device-mapper: ioctl: 4.37.0-ioctl (2017-09-20) initialised: dm-devel@redhat.com
[  527.314015] RPC: Registered named UNIX socket transport module.
[  527.317966] RPC: Registered udp transport module.
[  527.322213] RPC: Registered tcp transport module.
[  527.326353] RPC: Registered tcp NFSv4.1 backchannel transport module.
[  527.979629] cloud-init[1741]: Cloud-init v. 19.3-44.amzn2 running 'init-local' at Sat, 17 Jul 2021 22:20:00 +0000. Up 527.95 seconds.
[  528.248907] ena 0000:00:05.0 eth0: Local page cache is disabled for less than 16 channels
[  528.883966] cloud-init[2052]: Cloud-init v. 19.3-44.amzn2 running 'init' at Sat, 17 Jul 2021 22:20:01 +0000. Up 528.84 seconds.
[  528.903268] cloud-init[2052]: ci-info: ++++++++++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++++++++++++
[  528.903501] cloud-init[2052]: ci-info: +--------+------+----------------------------+---------------+--------+-------------------+
[  528.903641] cloud-init[2052]: ci-info: | Device |  Up  |          Address           |      Mask     | Scope  |     Hw-Address    |
[  528.903774] cloud-init[2052]: ci-info: +--------+------+----------------------------+---------------+--------+-------------------+
[  528.903900] cloud-init[2052]: ci-info: |  eth0  | True |       172.31.27.131        | 255.255.240.0 | global | 02:13:dd:43:53:31 |
[  528.904054] cloud-init[2052]: ci-info: |  eth0  | True | fe80::13:ddff:fe43:5331/64 |       .       |  link  | 02:13:dd:43:53:31 |
[  528.904210] cloud-init[2052]: ci-info: |   lo   | True |         127.0.0.1          |   255.0.0.0   |  host  |         .         |
[  528.904329] cloud-init[2052]: ci-info: |   lo   | True |          ::1/128           |       .       |  host  |         .         |
[  528.904447] cloud-init[2052]: ci-info: +--------+------+----------------------------+---------------+--------+-------------------+
[  528.904564] cloud-init[2052]: ci-info: ++++++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++++++++
[  528.904683] cloud-init[2052]: ci-info: +-------+-----------------+-------------+-----------------+-----------+-------+
[  528.904801] cloud-init[2052]: ci-info: | Route |   Destination   |   Gateway   |     Genmask     | Interface | Flags |
[  528.904916] cloud-init[2052]: ci-info: +-------+-----------------+-------------+-----------------+-----------+-------+
[  528.905037] cloud-init[2052]: ci-info: |   0   |     0.0.0.0     | 172.31.16.1 |     0.0.0.0     |    eth0   |   UG  |
[  528.905160] cloud-init[2052]: ci-info: |   1   | 169.254.169.254 |   0.0.0.0   | 255.255.255.255 |    eth0   |   UH  |
[  528.905276] cloud-init[2052]: ci-info: |   2   |   172.31.16.0   |   0.0.0.0   |  255.255.240.0  |    eth0   |   U   |
[  528.905399] cloud-init[2052]: ci-info: +-------+-----------------+-------------+-----------------+-----------+-------+
[  528.905515] cloud-init[2052]: ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
[  528.905636] cloud-init[2052]: ci-info: +-------+-------------+---------+-----------+-------+
[  528.905756] cloud-init[2052]: ci-info: | Route | Destination | Gateway | Interface | Flags |
[  528.905870] cloud-init[2052]: ci-info: +-------+-------------+---------+-----------+-------+
[  528.905984] cloud-init[2052]: ci-info: |   9   |  fe80::/64  |    ::   |    eth0   |   U   |
[  528.906101] cloud-init[2052]: ci-info: |   11  |    local    |    ::   |    eth0   |   U   |
[  528.906234] cloud-init[2052]: ci-info: |   12  |   ff00::/8  |    ::   |    eth0   |   U   |
[  528.906351] cloud-init[2052]: ci-info: +-------+-------------+---------+-----------+-------+
[  529.873525] cloud-init[2195]: Cloud-init v. 19.3-44.amzn2 running 'modules:config' at Sat, 17 Jul 2021 22:20:02 +0000. Up 529.78 seconds.
[  530.498964] cloud-init[2319]: Cloud-init v. 19.3-44.amzn2 running 'modules:final' at Sat, 17 Jul 2021 22:20:03 +0000. Up 530.41 seconds.
[  530.515298] cloud-init[2319]: Cloud-init v. 19.3-44.amzn2 finished at Sat, 17 Jul 2021 22:20:03 +0000. Datasource DataSourceEc2.  Up 530.51 seconds
2021/07/17 22:20:03Z: Amazon SSM Agent v3.0.1124.0 is running
2021/07/17 22:20:03Z: OsProductName: Amazon Linux
2021/07/17 22:20:03Z: OsVersion: 2

Amazon Linux 2
Kernel 4.14.232-177.418.amzn2.x86_64 on an x86_64

ip-172-31-27-131 login: root
Password: 
Last login: Sat Jul 17 22:09:47 on ttyS0

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
16 package(s) needed for security, out of 18 available
Run "sudo yum update" to apply all updates.
[root@ip-172-31-27-131 ~]# 
[root@ip-172-31-27-131 ~]#

「rm -rf /*」実行後に、緊急モードで起動できるのか確認

それでは、いよいよrm -rf /*実行後に、緊急モードで起動できるのか確認してみます。

シリアルコンソールでEC2インスタンスに接続した後、rm -rf /*を実行します。最初に実行した時と同様にOperation not permittedを出していますが、しばらく経つと以下のように削除が完了したようです。

緊急モードで起動するために、EC2インスタンスを停止、起動します。

起動後、再度シリアルコンソールでEC2インスタンスに接続しました。すると、何ということでしょう。最初にトライした時と同様にどんなキーを叩いても反応しません。

冷静になって考えると当然ですが、GRUBの設定ファイルがある/bootも削除されています。そのため、頼みの綱の緊急モードも使えませんでした。南無三。

rm -rf /*」を実行してしまったら、AMIからリストアしよう

今回は、rm -rf /*でOSを破壊してみました。

噂に違わぬとんでもないコマンドであることを確認しました。

もし、実行してしまった場合は、素直にAMIからリストアすることになると思います。
実行してコンマ数秒で気づいたならまだしも、しばらく経ってから気づいた場合は、どこまで削除してしまったかを確認して、削除したものだけをリストアする時間や手間は相当かかると想像します。

定期的にAMIを作成しているのであれば、そちらを利用してEC2インスタンスを丸ごとリストアした方が、結果としてリストア時間は早くなると思います。
なお、AMIを作成した時期がかなり前である場合は、大幅なデータロストが予想されるため要注意です。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!