SlideShare ist ein Scribd-Unternehmen logo
1 von 16
Research for y2038
はじめに
• 2038年問題がそろそろ気になる時期になってきたので、調べ始めました
• Linux Kernelの状況とユーザランドの整合がとれないといけない部分なので、かなりの長丁
場です
• 今回は、カーネルの中を見てみました
Linuxの2038年問題に関係するコンポーネント
• 多くのOSS/ユーザプログラム
• 内部での時刻の取り扱いは、それぞれの実装に依存
• 各プログラミング言語の時刻機能を
• libcが提供するデータ型、システムコール、ライブラリを用い
て機能を実現する
• ローカルタイムのはglibcが扱う
• タイムゾーン設定に基づいて、GMT/UTCとローカルタイム
の相互変換を担当
• 時刻はLinux Kernel内部で管理されている
• MONOTONIC時刻を担当(Power ON起点の時刻)
• カレンダー時刻を担当(カーネルはGMT/UTCのみを扱う)
Linux Kernel
Libc (glibc)
Runtime library (ex. libstdc++)
Generic OSS
Linux Kernelの2038年問題
• UNIXの時刻表現が、1970年1月1日0時0分0秒を起点とした秒カウンタになっており、その
カウンタが符号つき32bitであることから生じる問題
• 符号つき32bitは2,147,483,647を超えた時点でがオーバーフローするため、2038年1月19日
3時14分7秒以降の時刻を表現できないことから、2038年問題と呼ばれる
• Linuxには、この秒カウンタのデータ型time_tが2種類存在する
• 32bitアーキテクチャでは符号つき32bit
• 64bitアーキテクチャでは符号つき64bit
• 一般に、time_tが符号つき64bitである64bitアーキテクチャでは、2038年問題が発生しない
と言われている
• 計算上は約3000億年まで対応できる
Linux Kernelの分析
• 2020年に、32bit環境の2038年問題対応の最後のパッチがメインラインにマージされた
• https://lkml.org/lkml/2020/1/29/355?anz=web
• この対応は5.4LTSにもマージされている
• いつからはじまったのか?
• 32bit環境の2038年問題は、3.17から開始された
• https://www.deepl.com/translator#en/ja/Year%202038%20preparations%20in%203.17
• これらの歴史を紐解いていく
• 分析するカーネルバージョン
Kernel Version Release Year
3.10 2013 32bit環境の2038年問題対応が始まる前のLTSカーネル
4.14 2017 5.4のふたつ前のLTSカーネル
4.19 2018 5.4のひとつ前のLTSカーネル(CIPのSLTSカーネルでもある)
5.4 2019 32bit環境の2038年問題対応が完了したとされるカーネル
Linux Kernelの分析-5.4の状況
• Linuxの時刻設定システムコール
• stime : 秒制度のUNIX time設定システムコール
• Kerne 5.4では、time_tをそのまま受け渡すstimeと後方互換性のためのstime32が用意されている
• kernel/time/time.c
• ただし、64bit time_tが使えるstimeは一部のアーキテクチャ以外では無効化されている
• settimeofday : 旧形式のシステムコールで、timeval (秒+マイクロ秒)で時刻設定を行う
• Kerne 5.4では、 time_tをそのまま受け渡す実装と後方互換性のためのCOMPAT実装が用意されている
• kernel/time/time.c
• clock_settime : 新形式のシステムコールで、timespec (秒+ナノ秒)で時刻設定を行う
• Kerne 5.4では、 ユーザ空間とのやり取りを__kernel_timespecで行うため、32bit環境でも64bitの秒カウンタを使うこと
ができ、カーネル空間では2038年問題が発生しない
• kernel/time/posix-timers.c
• Linuxではtime_tがlong型なので、32bitでは4byte、64bitでは8byteで扱われる
• 5.4時点でのシステムコール実装は、stime, settimeofdayでは32bit環境で2038年問題を抱えており、
clock_settimeのみ対策されている
時刻設定の仕組み調査
• 32bitのarmカーネルを対象にシステムコール拡張を分析
• 調査のカギとなるパッチは「y2038: add 64-bit time_t syscalls to all 32-bit architectures」と思われる
• https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.4.94&id=48166e6ea47d23984f0b
481ca199250e1ce0730a
• このパッチでは、32bitアーキテクチャであるarm, m68k, x86などに対してシステムコールテーブルの追加が行われている
ので、これをもとに実装を追跡する
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index a96d9b5ee04e3..9016f4081bb9c 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -416,3 +416,24 @@
399 common io_pgetevents sys_io_pgetevents_time32
400 common migrate_pages sys_migrate_pages
401 common kexec_file_load sys_kexec_file_load
+# 402 is unused
+403 common clock_gettime64 sys_clock_gettime
+404 common clock_settime64 sys_clock_settime
+405 common clock_adjtime64 sys_clock_adjtime
+406 common clock_getres_time64 sys_clock_getres
+407 common clock_nanosleep_time64 sys_clock_nanosleep
+408 common timer_gettime64 sys_timer_gettime
+409 common timer_settime64 sys_timer_settime
+410 common timerfd_gettime64 sys_timerfd_gettime
+411 common timerfd_settime64 sys_timerfd_settime
+412 common utimensat_time64 sys_utimensat
+413 common pselect6_time64 sys_pselect6
+414 common ppoll_time64 sys_ppoll
+416 common io_pgetevents_time64 sys_io_pgetevents
+417 common recvmmsg_time64 sys_recvmmsg
+418 common mq_timedsend_time64 sys_mq_timedsend
+419 common mq_timedreceive_time64 sys_mq_timedreceive
+420 common semtimedop_time64 sys_semtimedop
+421 common rt_sigtimedwait_time64 sys_rt_sigtimedwait
+422 common futex_time64 sys_futex
+423 common sched_rr_get_interval_time64 sys_sched_rr_get_interval
事前調査の結果、32bit環境のシステムコール実装が2038
年問題を抱えているように見えたstime, settimeofdayは拡張
されていない。
32bit環境のシステムコール実装が2038年問題を解決してい
るように見えたclock_settimeに関しては、新しいシステムコー
ルであるclock_settime64とつながっている
他もあわせて計21種類の64bit time_tに対応したシステム
コールが用意されている
時刻設定の仕組み調査
• 64bitと32bitのシステムコール呼び出しの違い
• 32bitの場合
• clock_settime (syscall num. 262)は、32bit time_tを使う
実装(sys_clock_settime32)を呼び出す
• 新しいclock_settime64(syscall num. 404)は、64bit
time_tを使う実装(sys_clock_settime)を呼び出す
• stimeとsettimeofdayは、どの実装も32bit time_tしか扱え
ないので、呼び出す関数に意味はない
• 廃止予定でないシステムコールのみ64bit time_t対応した
と考えられる
• 64bitの場合
• clock_settime/clock_settime64ともに、64bit time_tを使
う(sys_clock_settime)を呼び出す
• settimeofdayは、64bitユーザランドの場合は64bit time_t
を使う実装(sys_settimeofday)を、32bitユーザランドの場
合は32bit time_tを使う実装(compat_sys_settimeofday)
を呼び出す
• stimeは、既に廃止扱いになっているシステムコールだから
か、syscall numすら割り当てられていない
Syscall
num.
Syscall name Syscall impl.
25 stime sys_stime32
79 settimeofday sys_settimeofday
262 clock_settime sys_clock_settime32
404 clock_settime64 sys_clock_settime
Syscall
num.
Syscall name Syscall impl.
112 clock_settime sys_clock_settime
170(64) settimeofday sys_settimeofday
170(32) settimeofday compat_sys_settimeofday
404 clock_settime64 sys_clock_settime
時刻設定の仕組み調査
• システムコール呼び出しから、実処理までを追跡
• カレンダー時刻は、最終的にはdo_settimeofday64を呼び出す
• do_settimeofday64まで、時刻はtimespec64/timespecで扱われる
do_settimeofday64
stime
stime32
do_sys_settimeofday64
settimeofday
settimeofday(compat)
posix_clock_realtime_set
clock_settime
clock_settime32
時刻設定の仕組み調査
• 時刻設定システムコールは、最終的には
do_settimeofday64を呼び出す
• 名前が示す通り、この関数は64bitで時間を取り扱
う
int do_settimeofday64(const struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts_delta, xt;
unsigned long flags;
int ret = 0;
if (!timespec64_valid_settod(ts))
return -EINVAL;
raw_spin_lock_irqsave(&timekeeper_lock, flags);
write_seqcount_begin(&tk_core.seq);
timekeeping_forward_now(tk);
xt = tk_xtime(tk);
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) {
ret = -EINVAL;
goto out;
}
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
tk_set_xtime(tk, ts);
out:
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* signal hrtimers about time change */
clock_was_set();
if (!ret)
audit_tk_injoffset(ts_delta);
return ret;
}
typedef __s64 time64_t;
struct timespec64 {
time64_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
時刻設定の仕組み調査
• 時刻設定システムコールは、最終的には
do_settimeofday64を呼び出す
• 名前が示す通り、この関数は64bitで時間を取り扱
う
• timespec64の値をチェックする
timespec64_valid_settodで有効値であることを
確認している
• Linux内ではこれ以降㎱カウンタであるktime_tで
時刻を取り扱う
• UNIX timeは64bitでも符号付きなので、負値は
異常値
• 64bitの UNIX timeよりもktime_tが先にオーバーフ
ローするので、上限値を超えた場合は異常値とし
て扱う
• TIME_UPTIME_SEC_MAXの計算式を見ると、30
年連続動作を想定しているように見える
• 2038年問題の次に、ktime_tのオーバーフロー
問題が存在している
int do_settimeofday64(const struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts_delta, xt;
unsigned long flags;
int ret = 0;
if (!timespec64_valid_settod(ts))
return -EINVAL;
raw_spin_lock_irqsave(&timekeeper_lock, flags);
write_seqcount_begin(&tk_core.seq);
timekeeping_forward_now(tk);
xt = tk_xtime(tk);
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) {
ret = -EINVAL;
goto out;
}
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
tk_set_xtime(tk, ts);
out:
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* signal hrtimers about time change */
clock_was_set();
if (!ret)
audit_tk_injoffset(ts_delta);
return ret;
}
static inline bool timespec64_valid_settod(const struct timespec64 *ts)
{
if (!timespec64_valid(ts))
return false;
/* Disallow values which cause overflow issues vs. CLOCK_REALTIME */
if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX)
return false;
return true;
}
#define TIME_SETTOD_SEC_MAX (KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX)
#define KTIME_MAX ((s64)~((u64)1 << 63))
#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
#define TIME_UPTIME_SEC_MAX (30LL * 365 * 24 *3600)
static inline bool timespec64_valid(const struct timespec64 *ts)
{
/* Dates before 1970 are bogus */
if (ts->tv_sec < 0)
return false;
/* Can't have more nanoseconds then a second */
if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
return false;
return true;
}
ktime_t はどのくらいもつのか?
• ktime_t は64bitのnsカウンタ
• typedef s64 ktime_t; なので、符号つきなのはtime_tと同じ
• 1000 = 1024 = 2^10 で概算すると、64 – 10 – 10 – 10 = 34なので、34bitが秒に割り当たっている
• 32bitのtime_tで約68年もつので、4倍の約272年もつ
• 近似計算なので実際はもう少し持ちます
• 時刻設定で連続稼働時間30年に耐えられるように設定可能な上限値を下げているため、実際には約242
年もつ計算になる
• これらを総合すると、1970+242=2212年が限界値(近似計算による値)になる
• 補足
• armなど一部のアーキテクチャを除くと、32bitアーキテクチャでは計算の高速化を狙ってか64bitのktime_tを
32bitの秒カウンタと32bitのnsカウンタに分けているものがあった
• この場合はktime_tが2038年にオーバーフローしてしまう
• 32bit環境でも、一律64bitの符号つきnsカウンタに統一する変更も行われている
その他の状況
• 時刻取得関係はktime_tからtime_tに変換される
• 64bit環境では、ktime_tの上限がそのまま実装上の上限となる
• 32bit環境では、clock_gettimeを除いてtime_tの上限が上限となる
• タイムアウト関係も同様
• futexのタイムアウト設定は__kernel_timespecを使っているため、カーネル空間では2038年問題は発生しな
い
LTSカーネルの状況
• 32bit環境で、2038年問題に部分的にでも対応するためには、 __kernel_timespecを使っ
ている必要がある
• 4.19のclock_settimeには使われているが、4.14のclock_settimeでは使われていない
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
const struct timespec __user *, tp)
{
const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 new_tp;
if (!kc || !kc->clock_set)
return -EINVAL;
if (get_timespec64(&new_tp, tp))
return -EFAULT;
return kc->clock_set(which_clock, &new_tp);
}
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
struct timespec __user *,tp)
{
const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 kernel_tp;
int error;
if (!kc)
return -EINVAL;
error = kc->clock_get(which_clock, &kernel_tp);
if (!error && put_timespec64(&kernel_tp, tp))
error = -EFAULT;
return error;
}
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
const struct __kernel_timespec __user *, tp)
{
const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 new_tp;
if (!kc || !kc->clock_set)
return -EINVAL;
if (get_timespec64(&new_tp, tp))
return -EFAULT;
return kc->clock_set(which_clock, &new_tp);
}
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
struct __kernel_timespec __user *, tp)
{
const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 kernel_tp;
int error;
if (!kc)
return -EINVAL;
error = kc->clock_get(which_clock, &kernel_tp);
if (!error && put_timespec64(&kernel_tp, tp))
error = -EFAULT;
return error;
}
4.14 4.19
LTSカーネルの状況
• 各バージョンの状況を見ると、一通り入っているとされている5.4を基準とすると
• 4.19は頑張ればいけるかもレベル
• 4.14はかなり無理がありそう
• ただし、キーとなっていそうなこの対応は5.4にしか入っていないので、4.19もつらそうではある
• https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.4.94&id=48166e6ea47d2
3984f0b481ca199250e1ce0730a
• パッチの状況
• 5.4
• https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=v5.4.94&qt=grep&q=y2038%3A
• 4.19
• https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=linux-4.19.y&qt=grep&q=y2038%3A
• 4.14
• https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=linux-4.14.y&qt=grep&q=y2038%3A
次は
• ユーザーランド。。。

Weitere ähnliche Inhalte

Was ist angesagt?

MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)NTT DATA Technology & Innovation
 
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)NTT DATA Technology & Innovation
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Nobuhiro Iwamatsu
 
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動する
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動するStargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動する
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動するKohei Tokunaga
 
Linux-HA Japanプロジェクトのこれまでとこれから
Linux-HA JapanプロジェクトのこれまでとこれからLinux-HA Japanプロジェクトのこれまでとこれから
Linux-HA Japanプロジェクトのこれまでとこれからksk_ha
 
Pacemakerを使いこなそう
Pacemakerを使いこなそうPacemakerを使いこなそう
Pacemakerを使いこなそうTakatoshi Matsuo
 
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)NTT DATA Technology & Innovation
 
今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門Masahito Zembutsu
 
OSTree: OSイメージとパッケージシステムの間にGitのアプローチを
OSTree: OSイメージとパッケージシステムの間にGitのアプローチをOSTree: OSイメージとパッケージシステムの間にGitのアプローチを
OSTree: OSイメージとパッケージシステムの間にGitのアプローチをi_yudai
 
Docker ComposeでMastodonが必要なものを梱包する話
Docker ComposeでMastodonが必要なものを梱包する話Docker ComposeでMastodonが必要なものを梱包する話
Docker ComposeでMastodonが必要なものを梱包する話Masahito Zembutsu
 
PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説Masahiko Sawada
 
Dockerのディスクについて ~ファイルシステム・マウント方法など~
Dockerのディスクについて ~ファイルシステム・マウント方法など~Dockerのディスクについて ~ファイルシステム・マウント方法など~
Dockerのディスクについて ~ファイルシステム・マウント方法など~HommasSlide
 
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSS
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSSYahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSS
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSSYahoo!デベロッパーネットワーク
 
DockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐるDockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐるKohei Tokunaga
 
TripleOの光と闇
TripleOの光と闇TripleOの光と闇
TripleOの光と闇Manabu Ori
 
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)NTT DATA Technology & Innovation
 
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)シスコシステムズ合同会社
 
DockerとPodmanの比較
DockerとPodmanの比較DockerとPodmanの比較
DockerとPodmanの比較Akihiro Suda
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話Kumazaki Hiroki
 
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...NTT DATA Technology & Innovation
 

Was ist angesagt? (20)

MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
MesonでPostgreSQLをビルドしてみよう!(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料
 
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動する
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動するStargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動する
Stargz Snapshotter: イメージのpullを省略しcontainerdでコンテナを高速に起動する
 
Linux-HA Japanプロジェクトのこれまでとこれから
Linux-HA JapanプロジェクトのこれまでとこれからLinux-HA Japanプロジェクトのこれまでとこれから
Linux-HA Japanプロジェクトのこれまでとこれから
 
Pacemakerを使いこなそう
Pacemakerを使いこなそうPacemakerを使いこなそう
Pacemakerを使いこなそう
 
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門
 
OSTree: OSイメージとパッケージシステムの間にGitのアプローチを
OSTree: OSイメージとパッケージシステムの間にGitのアプローチをOSTree: OSイメージとパッケージシステムの間にGitのアプローチを
OSTree: OSイメージとパッケージシステムの間にGitのアプローチを
 
Docker ComposeでMastodonが必要なものを梱包する話
Docker ComposeでMastodonが必要なものを梱包する話Docker ComposeでMastodonが必要なものを梱包する話
Docker ComposeでMastodonが必要なものを梱包する話
 
PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説
 
Dockerのディスクについて ~ファイルシステム・マウント方法など~
Dockerのディスクについて ~ファイルシステム・マウント方法など~Dockerのディスクについて ~ファイルシステム・マウント方法など~
Dockerのディスクについて ~ファイルシステム・マウント方法など~
 
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSS
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSSYahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSS
Yahoo! JAPANのプライベートRDBクラウドとマルチライター型 MySQL #dbts2017 #dbtsOSS
 
DockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐるDockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐる
 
TripleOの光と闇
TripleOの光と闇TripleOの光と闇
TripleOの光と闇
 
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
 
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)
Cisco Modeling Labs (CML)を使ってネットワークを学ぼう!(DevNet編)
 
DockerとPodmanの比較
DockerとPodmanの比較DockerとPodmanの比較
DockerとPodmanの比較
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...
OSSプロジェクトへのコントリビューション はじめの一歩を踏み出そう!(Open Source Conference 2022 Online/Spring...
 

Ähnlich wie Linuxの2038年問題を調べてみた

Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)NTT DATA Technology & Innovation
 
Softflowd_49.7d_20160723
Softflowd_49.7d_20160723Softflowd_49.7d_20160723
Softflowd_49.7d_20160723Takashi Umeno
 
Spmv9forpublic
Spmv9forpublicSpmv9forpublic
Spmv9forpublicT2C_
 
システムパフォーマンス勉強会#5
システムパフォーマンス勉強会#5システムパフォーマンス勉強会#5
システムパフォーマンス勉強会#5shingo suzuki
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Hiraku Toyooka
 
3GPP 5G NSA introduction 2(EN-DC RRC Timer)
3GPP 5G NSA introduction 2(EN-DC RRC Timer)3GPP 5G NSA introduction 2(EN-DC RRC Timer)
3GPP 5G NSA introduction 2(EN-DC RRC Timer)Ryuichi Yasunaga
 
Docker & Kubernetes基礎
Docker & Kubernetes基礎Docker & Kubernetes基礎
Docker & Kubernetes基礎Daisuke Hiraoka
 
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題Makoto Setoh
 
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)NTT DATA Technology & Innovation
 
EnrootとPyxisで快適コンテナ生活
EnrootとPyxisで快適コンテナ生活EnrootとPyxisで快適コンテナ生活
EnrootとPyxisで快適コンテナ生活Kuninobu SaSaki
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code readingMasami Hiramatsu
 
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)NTT DATA Technology & Innovation
 
Kubernetes、Flannel、CNIでWindows Container Clusterオーケストレーション
Kubernetes、Flannel、CNIでWindows Container ClusterオーケストレーションKubernetes、Flannel、CNIでWindows Container Clusterオーケストレーション
Kubernetes、Flannel、CNIでWindows Container ClusterオーケストレーションTakashi Kanai
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 sandai
 
BigQueryの課金、節約しませんか
BigQueryの課金、節約しませんかBigQueryの課金、節約しませんか
BigQueryの課金、節約しませんかRyuji Tamagawa
 
Rtコンポーネント作成入門
Rtコンポーネント作成入門Rtコンポーネント作成入門
Rtコンポーネント作成入門openrtm
 
20131230_CloudStack Advent Calendar VPCを作ってみよう
20131230_CloudStack Advent Calendar VPCを作ってみよう20131230_CloudStack Advent Calendar VPCを作ってみよう
20131230_CloudStack Advent Calendar VPCを作ってみようMidori Oge
 
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみた
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみたKubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみた
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみたAkihito Inoh
 

Ähnlich wie Linuxの2038年問題を調べてみた (20)

Clock / Timer
Clock / TimerClock / Timer
Clock / Timer
 
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
Softflowd_49.7d_20160723
Softflowd_49.7d_20160723Softflowd_49.7d_20160723
Softflowd_49.7d_20160723
 
Spmv9forpublic
Spmv9forpublicSpmv9forpublic
Spmv9forpublic
 
システムパフォーマンス勉強会#5
システムパフォーマンス勉強会#5システムパフォーマンス勉強会#5
システムパフォーマンス勉強会#5
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
 
SystemV IPC
SystemV IPCSystemV IPC
SystemV IPC
 
3GPP 5G NSA introduction 2(EN-DC RRC Timer)
3GPP 5G NSA introduction 2(EN-DC RRC Timer)3GPP 5G NSA introduction 2(EN-DC RRC Timer)
3GPP 5G NSA introduction 2(EN-DC RRC Timer)
 
Docker & Kubernetes基礎
Docker & Kubernetes基礎Docker & Kubernetes基礎
Docker & Kubernetes基礎
 
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
 
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)
Java 18で入ったJVM関連の(やや細かめな)改善(JJUGナイトセミナー「Java 18 リリース記念イベント」発表資料)
 
EnrootとPyxisで快適コンテナ生活
EnrootとPyxisで快適コンテナ生活EnrootとPyxisで快適コンテナ生活
EnrootとPyxisで快適コンテナ生活
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code reading
 
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)
Postgres Playground で pgbench を走らせよう!(第35回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
Kubernetes、Flannel、CNIでWindows Container Clusterオーケストレーション
Kubernetes、Flannel、CNIでWindows Container ClusterオーケストレーションKubernetes、Flannel、CNIでWindows Container Clusterオーケストレーション
Kubernetes、Flannel、CNIでWindows Container Clusterオーケストレーション
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
BigQueryの課金、節約しませんか
BigQueryの課金、節約しませんかBigQueryの課金、節約しませんか
BigQueryの課金、節約しませんか
 
Rtコンポーネント作成入門
Rtコンポーネント作成入門Rtコンポーネント作成入門
Rtコンポーネント作成入門
 
20131230_CloudStack Advent Calendar VPCを作ってみよう
20131230_CloudStack Advent Calendar VPCを作ってみよう20131230_CloudStack Advent Calendar VPCを作ってみよう
20131230_CloudStack Advent Calendar VPCを作ってみよう
 
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみた
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみたKubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみた
Kubernetes Meetup Tokyo #8 Self-hosted Kubernetes を調べてみた
 

Mehr von wata2ki

鹿児島らぐハイブリッド開催への道
鹿児島らぐハイブリッド開催への道鹿児島らぐハイブリッド開催への道
鹿児島らぐハイブリッド開催への道wata2ki
 
YoctoLTSについて調べてみた
YoctoLTSについて調べてみたYoctoLTSについて調べてみた
YoctoLTSについて調べてみたwata2ki
 
しょしんしゃのためのhello world
しょしんしゃのためのhello worldしょしんしゃのためのhello world
しょしんしゃのためのhello worldwata2ki
 
Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る wata2ki
 
ARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくいARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくいwata2ki
 
Fireduck
FireduckFireduck
Fireduckwata2ki
 
パッチを投稿してみた話
パッチを投稿してみた話パッチを投稿してみた話
パッチを投稿してみた話wata2ki
 
Linux kernelのbspとupstream
Linux kernelのbspとupstreamLinux kernelのbspとupstream
Linux kernelのbspとupstreamwata2ki
 

Mehr von wata2ki (8)

鹿児島らぐハイブリッド開催への道
鹿児島らぐハイブリッド開催への道鹿児島らぐハイブリッド開催への道
鹿児島らぐハイブリッド開催への道
 
YoctoLTSについて調べてみた
YoctoLTSについて調べてみたYoctoLTSについて調べてみた
YoctoLTSについて調べてみた
 
しょしんしゃのためのhello world
しょしんしゃのためのhello worldしょしんしゃのためのhello world
しょしんしゃのためのhello world
 
Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る 
 
ARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくいARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくい
 
Fireduck
FireduckFireduck
Fireduck
 
パッチを投稿してみた話
パッチを投稿してみた話パッチを投稿してみた話
パッチを投稿してみた話
 
Linux kernelのbspとupstream
Linux kernelのbspとupstreamLinux kernelのbspとupstream
Linux kernelのbspとupstream
 

Linuxの2038年問題を調べてみた

  • 2. はじめに • 2038年問題がそろそろ気になる時期になってきたので、調べ始めました • Linux Kernelの状況とユーザランドの整合がとれないといけない部分なので、かなりの長丁 場です • 今回は、カーネルの中を見てみました
  • 3. Linuxの2038年問題に関係するコンポーネント • 多くのOSS/ユーザプログラム • 内部での時刻の取り扱いは、それぞれの実装に依存 • 各プログラミング言語の時刻機能を • libcが提供するデータ型、システムコール、ライブラリを用い て機能を実現する • ローカルタイムのはglibcが扱う • タイムゾーン設定に基づいて、GMT/UTCとローカルタイム の相互変換を担当 • 時刻はLinux Kernel内部で管理されている • MONOTONIC時刻を担当(Power ON起点の時刻) • カレンダー時刻を担当(カーネルはGMT/UTCのみを扱う) Linux Kernel Libc (glibc) Runtime library (ex. libstdc++) Generic OSS
  • 4. Linux Kernelの2038年問題 • UNIXの時刻表現が、1970年1月1日0時0分0秒を起点とした秒カウンタになっており、その カウンタが符号つき32bitであることから生じる問題 • 符号つき32bitは2,147,483,647を超えた時点でがオーバーフローするため、2038年1月19日 3時14分7秒以降の時刻を表現できないことから、2038年問題と呼ばれる • Linuxには、この秒カウンタのデータ型time_tが2種類存在する • 32bitアーキテクチャでは符号つき32bit • 64bitアーキテクチャでは符号つき64bit • 一般に、time_tが符号つき64bitである64bitアーキテクチャでは、2038年問題が発生しない と言われている • 計算上は約3000億年まで対応できる
  • 5. Linux Kernelの分析 • 2020年に、32bit環境の2038年問題対応の最後のパッチがメインラインにマージされた • https://lkml.org/lkml/2020/1/29/355?anz=web • この対応は5.4LTSにもマージされている • いつからはじまったのか? • 32bit環境の2038年問題は、3.17から開始された • https://www.deepl.com/translator#en/ja/Year%202038%20preparations%20in%203.17 • これらの歴史を紐解いていく • 分析するカーネルバージョン Kernel Version Release Year 3.10 2013 32bit環境の2038年問題対応が始まる前のLTSカーネル 4.14 2017 5.4のふたつ前のLTSカーネル 4.19 2018 5.4のひとつ前のLTSカーネル(CIPのSLTSカーネルでもある) 5.4 2019 32bit環境の2038年問題対応が完了したとされるカーネル
  • 6. Linux Kernelの分析-5.4の状況 • Linuxの時刻設定システムコール • stime : 秒制度のUNIX time設定システムコール • Kerne 5.4では、time_tをそのまま受け渡すstimeと後方互換性のためのstime32が用意されている • kernel/time/time.c • ただし、64bit time_tが使えるstimeは一部のアーキテクチャ以外では無効化されている • settimeofday : 旧形式のシステムコールで、timeval (秒+マイクロ秒)で時刻設定を行う • Kerne 5.4では、 time_tをそのまま受け渡す実装と後方互換性のためのCOMPAT実装が用意されている • kernel/time/time.c • clock_settime : 新形式のシステムコールで、timespec (秒+ナノ秒)で時刻設定を行う • Kerne 5.4では、 ユーザ空間とのやり取りを__kernel_timespecで行うため、32bit環境でも64bitの秒カウンタを使うこと ができ、カーネル空間では2038年問題が発生しない • kernel/time/posix-timers.c • Linuxではtime_tがlong型なので、32bitでは4byte、64bitでは8byteで扱われる • 5.4時点でのシステムコール実装は、stime, settimeofdayでは32bit環境で2038年問題を抱えており、 clock_settimeのみ対策されている
  • 7. 時刻設定の仕組み調査 • 32bitのarmカーネルを対象にシステムコール拡張を分析 • 調査のカギとなるパッチは「y2038: add 64-bit time_t syscalls to all 32-bit architectures」と思われる • https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.4.94&id=48166e6ea47d23984f0b 481ca199250e1ce0730a • このパッチでは、32bitアーキテクチャであるarm, m68k, x86などに対してシステムコールテーブルの追加が行われている ので、これをもとに実装を追跡する diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index a96d9b5ee04e3..9016f4081bb9c 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -416,3 +416,24 @@ 399 common io_pgetevents sys_io_pgetevents_time32 400 common migrate_pages sys_migrate_pages 401 common kexec_file_load sys_kexec_file_load +# 402 is unused +403 common clock_gettime64 sys_clock_gettime +404 common clock_settime64 sys_clock_settime +405 common clock_adjtime64 sys_clock_adjtime +406 common clock_getres_time64 sys_clock_getres +407 common clock_nanosleep_time64 sys_clock_nanosleep +408 common timer_gettime64 sys_timer_gettime +409 common timer_settime64 sys_timer_settime +410 common timerfd_gettime64 sys_timerfd_gettime +411 common timerfd_settime64 sys_timerfd_settime +412 common utimensat_time64 sys_utimensat +413 common pselect6_time64 sys_pselect6 +414 common ppoll_time64 sys_ppoll +416 common io_pgetevents_time64 sys_io_pgetevents +417 common recvmmsg_time64 sys_recvmmsg +418 common mq_timedsend_time64 sys_mq_timedsend +419 common mq_timedreceive_time64 sys_mq_timedreceive +420 common semtimedop_time64 sys_semtimedop +421 common rt_sigtimedwait_time64 sys_rt_sigtimedwait +422 common futex_time64 sys_futex +423 common sched_rr_get_interval_time64 sys_sched_rr_get_interval 事前調査の結果、32bit環境のシステムコール実装が2038 年問題を抱えているように見えたstime, settimeofdayは拡張 されていない。 32bit環境のシステムコール実装が2038年問題を解決してい るように見えたclock_settimeに関しては、新しいシステムコー ルであるclock_settime64とつながっている 他もあわせて計21種類の64bit time_tに対応したシステム コールが用意されている
  • 8. 時刻設定の仕組み調査 • 64bitと32bitのシステムコール呼び出しの違い • 32bitの場合 • clock_settime (syscall num. 262)は、32bit time_tを使う 実装(sys_clock_settime32)を呼び出す • 新しいclock_settime64(syscall num. 404)は、64bit time_tを使う実装(sys_clock_settime)を呼び出す • stimeとsettimeofdayは、どの実装も32bit time_tしか扱え ないので、呼び出す関数に意味はない • 廃止予定でないシステムコールのみ64bit time_t対応した と考えられる • 64bitの場合 • clock_settime/clock_settime64ともに、64bit time_tを使 う(sys_clock_settime)を呼び出す • settimeofdayは、64bitユーザランドの場合は64bit time_t を使う実装(sys_settimeofday)を、32bitユーザランドの場 合は32bit time_tを使う実装(compat_sys_settimeofday) を呼び出す • stimeは、既に廃止扱いになっているシステムコールだから か、syscall numすら割り当てられていない Syscall num. Syscall name Syscall impl. 25 stime sys_stime32 79 settimeofday sys_settimeofday 262 clock_settime sys_clock_settime32 404 clock_settime64 sys_clock_settime Syscall num. Syscall name Syscall impl. 112 clock_settime sys_clock_settime 170(64) settimeofday sys_settimeofday 170(32) settimeofday compat_sys_settimeofday 404 clock_settime64 sys_clock_settime
  • 9. 時刻設定の仕組み調査 • システムコール呼び出しから、実処理までを追跡 • カレンダー時刻は、最終的にはdo_settimeofday64を呼び出す • do_settimeofday64まで、時刻はtimespec64/timespecで扱われる do_settimeofday64 stime stime32 do_sys_settimeofday64 settimeofday settimeofday(compat) posix_clock_realtime_set clock_settime clock_settime32
  • 10. 時刻設定の仕組み調査 • 時刻設定システムコールは、最終的には do_settimeofday64を呼び出す • 名前が示す通り、この関数は64bitで時間を取り扱 う int do_settimeofday64(const struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 ts_delta, xt; unsigned long flags; int ret = 0; if (!timespec64_valid_settod(ts)) return -EINVAL; raw_spin_lock_irqsave(&timekeeper_lock, flags); write_seqcount_begin(&tk_core.seq); timekeeping_forward_now(tk); xt = tk_xtime(tk); ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { ret = -EINVAL; goto out; } tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); tk_set_xtime(tk, ts); out: timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); write_seqcount_end(&tk_core.seq); raw_spin_unlock_irqrestore(&timekeeper_lock, flags); /* signal hrtimers about time change */ clock_was_set(); if (!ret) audit_tk_injoffset(ts_delta); return ret; } typedef __s64 time64_t; struct timespec64 { time64_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
  • 11. 時刻設定の仕組み調査 • 時刻設定システムコールは、最終的には do_settimeofday64を呼び出す • 名前が示す通り、この関数は64bitで時間を取り扱 う • timespec64の値をチェックする timespec64_valid_settodで有効値であることを 確認している • Linux内ではこれ以降㎱カウンタであるktime_tで 時刻を取り扱う • UNIX timeは64bitでも符号付きなので、負値は 異常値 • 64bitの UNIX timeよりもktime_tが先にオーバーフ ローするので、上限値を超えた場合は異常値とし て扱う • TIME_UPTIME_SEC_MAXの計算式を見ると、30 年連続動作を想定しているように見える • 2038年問題の次に、ktime_tのオーバーフロー 問題が存在している int do_settimeofday64(const struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 ts_delta, xt; unsigned long flags; int ret = 0; if (!timespec64_valid_settod(ts)) return -EINVAL; raw_spin_lock_irqsave(&timekeeper_lock, flags); write_seqcount_begin(&tk_core.seq); timekeeping_forward_now(tk); xt = tk_xtime(tk); ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { ret = -EINVAL; goto out; } tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); tk_set_xtime(tk, ts); out: timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); write_seqcount_end(&tk_core.seq); raw_spin_unlock_irqrestore(&timekeeper_lock, flags); /* signal hrtimers about time change */ clock_was_set(); if (!ret) audit_tk_injoffset(ts_delta); return ret; } static inline bool timespec64_valid_settod(const struct timespec64 *ts) { if (!timespec64_valid(ts)) return false; /* Disallow values which cause overflow issues vs. CLOCK_REALTIME */ if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX) return false; return true; } #define TIME_SETTOD_SEC_MAX (KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX) #define KTIME_MAX ((s64)~((u64)1 << 63)) #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) #define TIME_UPTIME_SEC_MAX (30LL * 365 * 24 *3600) static inline bool timespec64_valid(const struct timespec64 *ts) { /* Dates before 1970 are bogus */ if (ts->tv_sec < 0) return false; /* Can't have more nanoseconds then a second */ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return false; return true; }
  • 12. ktime_t はどのくらいもつのか? • ktime_t は64bitのnsカウンタ • typedef s64 ktime_t; なので、符号つきなのはtime_tと同じ • 1000 = 1024 = 2^10 で概算すると、64 – 10 – 10 – 10 = 34なので、34bitが秒に割り当たっている • 32bitのtime_tで約68年もつので、4倍の約272年もつ • 近似計算なので実際はもう少し持ちます • 時刻設定で連続稼働時間30年に耐えられるように設定可能な上限値を下げているため、実際には約242 年もつ計算になる • これらを総合すると、1970+242=2212年が限界値(近似計算による値)になる • 補足 • armなど一部のアーキテクチャを除くと、32bitアーキテクチャでは計算の高速化を狙ってか64bitのktime_tを 32bitの秒カウンタと32bitのnsカウンタに分けているものがあった • この場合はktime_tが2038年にオーバーフローしてしまう • 32bit環境でも、一律64bitの符号つきnsカウンタに統一する変更も行われている
  • 13. その他の状況 • 時刻取得関係はktime_tからtime_tに変換される • 64bit環境では、ktime_tの上限がそのまま実装上の上限となる • 32bit環境では、clock_gettimeを除いてtime_tの上限が上限となる • タイムアウト関係も同様 • futexのタイムアウト設定は__kernel_timespecを使っているため、カーネル空間では2038年問題は発生しな い
  • 14. LTSカーネルの状況 • 32bit環境で、2038年問題に部分的にでも対応するためには、 __kernel_timespecを使っ ている必要がある • 4.19のclock_settimeには使われているが、4.14のclock_settimeでは使われていない SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct timespec __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 new_tp; if (!kc || !kc->clock_set) return -EINVAL; if (get_timespec64(&new_tp, tp)) return -EFAULT; return kc->clock_set(which_clock, &new_tp); } SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, struct timespec __user *,tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 kernel_tp; int error; if (!kc) return -EINVAL; error = kc->clock_get(which_clock, &kernel_tp); if (!error && put_timespec64(&kernel_tp, tp)) error = -EFAULT; return error; } SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct __kernel_timespec __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 new_tp; if (!kc || !kc->clock_set) return -EINVAL; if (get_timespec64(&new_tp, tp)) return -EFAULT; return kc->clock_set(which_clock, &new_tp); } SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, struct __kernel_timespec __user *, tp) { const struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec64 kernel_tp; int error; if (!kc) return -EINVAL; error = kc->clock_get(which_clock, &kernel_tp); if (!error && put_timespec64(&kernel_tp, tp)) error = -EFAULT; return error; } 4.14 4.19
  • 15. LTSカーネルの状況 • 各バージョンの状況を見ると、一通り入っているとされている5.4を基準とすると • 4.19は頑張ればいけるかもレベル • 4.14はかなり無理がありそう • ただし、キーとなっていそうなこの対応は5.4にしか入っていないので、4.19もつらそうではある • https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.4.94&id=48166e6ea47d2 3984f0b481ca199250e1ce0730a • パッチの状況 • 5.4 • https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=v5.4.94&qt=grep&q=y2038%3A • 4.19 • https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=linux-4.19.y&qt=grep&q=y2038%3A • 4.14 • https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=linux-4.14.y&qt=grep&q=y2038%3A