先日当ブログでも解決方法を紹介した、ネット上で騒がれているiOSのシステム時間を1970/1/1に設定してからシステムを再起動すると起動できなくなる問題。
しかもこの問題はA7チップ以降(iPhoneでいえばiPhone 5s以降)の64bitのプロセッサチップ(SoC)を搭載した機種でしか発生しない。ではなぜこの問題が発生するのか?当記事では詳細の原因を解説したい(といっても64bitデバイスでしか発生しないということについてはまだ疑問が残る)。そしてその解決方法の追記をご紹介する。上の記事と併せてご覧いただきたい。
1970/1/1問題の原因の解説
基礎知識:UNIX時刻
まずはこの問題が起こる原因として、iOSが使用している”UNIX時刻”についてあらかじめ頭に入れていただければと思う。
【UNIX時刻(UNIX time)とは】
UNIX time(ユニックスタイム)、POSIX time(ポジックスタイム)とはコンピューターシステム上での時刻表現の一種。UNIXエポック、すなわち協定世界時 (UTC) での1970年1月1日真夜中(午前0時0分0秒)の時刻からの形式的な経過秒数(すなわち、実質的な経過秒数から、その間に挿入された閏秒を引き、削除された閏秒を加えたもの)として表される。
そしてiOSシステムでの時刻表示は、このUNIX時刻を利用したデータ型time_tを利用している。そしてシステムの中では、これを2進数で管理している。
UNIXエポックの規定では、1秒が経つたびにその2進数に1を足していくとされている。
桁が溢れるとマイナス時刻になる、32bitデバイス特有の【2038年問題】
一部の好奇心に溢れた人は、1970年1月1日より過去に調整できないのであれば、未来に調整してはどうだろうと考えるだろう。そして実際にやってみた人は、iOSシステムで設置可能な最後の時間は2038年1月1日で、それ以降の時刻には設定できないことに気づくに違いない。Appleはそれ以降に設置することで起こる問題について考慮の上で故意にそうしている。ではなぜそういえるのだろうか?
32bitのシステムで、UNIX時刻を記録する2進数のtime_tの最大の桁数は32桁で、符号付き整数型(signed integer type、整数を格納するデータ型の一種で、0と正の数以外に負の数も表現できる整数型)だ。最初の2進数の1桁は符号で、正数(0)か負数(1)かを表す。そして正数は1970/1/1(UNIXエポック)以降の時間を表し、負数はその逆だ。つまり最初の1桁を除いた残りの31桁で経過した秒数を表している(細かくいうとUNIX時刻には閏秒の調整などもあり、正確に経過した時間を表しているものではないが、その話は上記のWikipediaでじっくりご覧いただきたい)。
そして時間が2038年1月19日3時14分07秒になった時、後ろの31桁の全ての数字が1になり、2038年1月19日3時14分08秒になると最初の1桁目が1になって後ろの31桁は全て0になる。そうなると時間が逆戻りする現象が起き、システムの時間は1901年12月13日20時45分52秒となり、システムはエラーを起こしてしまうのだ。
ここにわかりやすい動画(アニメgif)があるのでよくご覧いただきたい。一番下のDateが2038年1月19日3時14分08秒になった時が見物だ。
そういうわけで、Appleはこの問題が発生するのを見越して、2038年1月1日23時59分59秒までにしか設定できないようにしているというわけだ。もし誰かが好奇心でそのように設定したとしてもその後18日間は再設定の猶予期間がある計算になる上に、実際にその時期が来たとしてもそもそも今から22年後の2038年になったら32bitデバイスは完全に時代遅れになっていて淘汰されていることだろう(2016年の現在でもiPhone 4sなどの32bit機は既に時代遅れ感があるほどだ)。ちなみにこれは2038年問題(Year 2038 problem)と呼ばれている。
ちなみに上記のように未来に設定することについては64bitデバイスのシステムでは影響を受けない。なぜだろうか?お察しの通り、64bitシステムではUNIX時刻のtime-tを2進数の64桁で記録しているため、計算してみると292,277,026,596年12月04日15時30分08秒が最終時間となる。すなわち西暦2922億年7702万6596年ということになり、正直殆ど想像もつかないほどの未来(太陽や地球の寿命より断然先の話)なので心配はいらないというわけだ。
なぜ1970/01/01(UNIXエポック)に戻すと問題が出るのか
では上記の知識を踏まえた上で、本題に戻ろう。なぜ1970/01/01(UNIXエポック)に設定すると問題が起こるのだろうか?
先ほど書いたとおり、UNIX時刻はUTC時刻の1970年1月1日0時0分0秒を境(0)として、時間が正常に流れれば正数、そして遡ると負の数となる。しかし注意しなければならないのは、”時差=タイムゾーン”だ。
例えば日本時間の場合、時間を1970年1月1日の0時0分0秒に設定すると、協定世界時(UTC)に対して日本時間は9時間プラス(日本時間=UTC+9)されていることになるので、UTCだと時間が1969年12月31日15時0分0秒となる。そうなると時刻がマイナスになってしまい、時間が遡るバグが発生したと判定される。するとシステムはKernelの段階でタイムエラーを起こし、デバイスが起動しなくなる、というわけだ。
64bitデバイスのみ問題が発生する原因については未だに不明
しかし、これは32bitでも64bitでも等しく発生する問題のはずだが、今回の問題は64bitデバイスのみにしか発生しない。その原因についてはまだわからない。完全に個人的な推測だが以下の可能性が考えられるかもしれない。
- 32bitと64bitデバイスでは時間の遡りに対する処理が異なっている?
- 64bitだと負の桁数が多くて処理できない?
- 64bitのみ何らかの原因で0の除算をしようとしてエラーが発生している?
1970/01/01に設定すると正常起動しなくなる問題が発生する条件
ここで整理。以下の条件を満たすと、時間の逆戻りバグが発生する。
【iOSのバージョン】
iOS 8.0〜iOS 9.3 beta 3(2016年2月14日現在)
【ハードウェアデバイス】
64bitプロセッサを搭載したデバイス(すなわちA7〜A9X搭載デバイス)
【問題が発生するデバイス一覧】
- A7チップ:iPhone 5s, iPad mini 2, iPad mini 3
- A7チップ強化型:iPad Air
- A8チップ:iPhone 6, iPhone 6 Plus, iPod Touch 6G, Apple TV 4G, iPad mini 4
- A8Xチップ:iPad Air
- A9(Samsung, TSMC):iPhone 6s, iPhone 6s Plus
- A9X:iPad Pro
【問題を発生させる方法】
設定-一般-日付と時間で自動設定をオフにし、時間を1970年1月1日に設定(時刻は任意)、そしてデバイスを再起動する。
【問題による症状】
iOSデバイスの起動の際、Appleのロゴマークが表示された状態でフリーズ(クラッシュ)し、正常に起動しなくなる。
1970/01/01に設定して正常に起動しない場合の解決方法
再度になるが、当ブログの以前の記事で3つの方法を紹介している。
それ以外の方法もあるのでご紹介。
数時間〜1日以上放置してからもう一度起動する
問題はタイムゾーンによる時間の遡りによって起こっているため、数時間〜1日以上放置すれば、上記で説明したUNIX時刻が0以上になるため、システムは正常に起動するようになる。
予防策
【要脱獄】脱獄Tweakによって日付・時刻を変更不可能にしフリーズ(クラッシュ)を防ぐ
方法は以下の通り。
- Cydiaを起動し、ソースに【http://repo.ziph0n.com/】を追加する
- 脱獄Tweakの【BrickingDate】をインストールしてRespring
- 設定>一般>日付と時刻の設定画面がこのようになって手動では日付と時刻を設定できなくなる
この脱獄Tweakは手動で時間を変更できなくするためのTweakだ。つまり他人に悪意を持って1970/1/1バグを仕掛けられないための予防策といえる。もちろん脱獄Tweak【BrickingDate】を削除すれば再度手動で設定可能となる。
新たなる懸念:悪意のある人からの攻撃
悪意のある攻撃者は、上記のバグを利用して無線LANを使って広範囲の攻撃を仕掛けることが可能だ。上の脱獄Tweak【BrickingDate】で手動での日付・時刻の変更を不可能にしていても予防できない(BrickingDateを入れる前に手動設定にしておけば対策できるかもしれない)
iOSは時刻を自動設定にしておくと、公共の無線LANネットワークでNTPサービスによってタイムゾーンや時間の自動調整を行うようになっている。もし悪意のある攻撃者がNTP攻撃を仕掛け、iOSシステムの時間(UNIX時刻)を上記のUTCでマイナスの時刻(UNIXエポックの1970/01/01以前)に変更し、ユーザがそれに気づかずにデバイスを再起動すると正常に起動しなくなるというわけだ。
Appleも対策中
自身で勝手に不必要な過去の時刻に設定するのはユーザの責任ではあるのだが、上記のような悪意を持った人に攻撃される懸念があるため、Appleは既に報告を受け対策に動いているという。iOSレベルでなんとかなる問題と思われるので、次回のiOS更新ではこの問題が修正されている可能性が高い。最も簡単な解決方法としてはOSレベルで1970/1/2以降にしか時間を設定できないようにすればいくら時差があっても問題がなくなるだろう。
(2016/2/15追記)
Appleは公式サイトのサポートページでこの「1970年問題」について、次回のソフトウェア・アップデート(=iOSのアップデート)で対策することを正式に表明した。
記事は以上。
(記事参考元:tgbus)