SlideShare ist ein Scribd-Unternehmen logo
1 von 22
Downloaden Sie, um offline zu lesen
golang binary hacks
2019-06-18 Takeshi Yaegashi
golang.tokyo #25
自己紹介
八重樫 剛史 Takeshi Yaegashi
● 株式会社バンダイナムコスタジオ所属
● Linux・Unix・OSS・低レベルなことが好きなエンジニア
● もちろん Go 言語も大好きです!
● Go を使ったお仕事
○ IoT 案件の Raspberry Pi 制御プログラム
○ スマホゲームアプリのサーバ
https://l0w.dev
最近レベルの低いドメインを取得したのでホームページとブログを作り直した
Hugo で生成したサイトを gitlab.com の GitLab Pages でホスト
下図は l0w.dev と low.dev の価値の比較
Hugo
Hugo は Go 言語で書かれた静的サイトジェネレータ
● https://gohugo.io
● Hugo には 2 種類あり、それぞれのバイナリが配布されている
○ Hugo
■ 基本機能のみの Hugo
○ Hugo Extended
■ SASS/SCSS のアセット処理もできる拡張版 Hugo
■ C++ で書かれたライブラリ libsass を組み込んでいる (cgo)
Hugo Extended on Docker
先日 gitlab.com/pages/hugo に対してコントリビュートした
● https://gitlab.com/pages/hugo/merge_requests/83
● プロジェクト Docker レジストリに hugo_extended イメージを追加
○ registry.gitlab.com/pages/hugo/hugo
○ registry.gitlab.com/pages/hugo/hugo_extended
● GitHub の Release からビルドされたバイナリをダウンロードして
Alpine Linux のコンテナで動かす、よくある構成
Hugo Extended on Alpine Linux
その後 hugo_extended イメージが動かないという報告がきた
● https://gitlab.com/pages/hugo/issues/31
● 複雑な SCSS を含むサイトで Segmentation fault が起きるらしい
● 同じ問題を抱えている人が結構多いらしい
○ Alpine Linux を使っているとだめ
○ musl libc だと動かない glibc だと動く
musl libc
musl は glibc と ABI 互換性のある Linux 用軽量 C ランタイムライブラリ
● https://www.musl-libc.org
● コンテナ容量削減の目的で Alpine Linux などで使われている
● glibc でビルドした実行ファイルがそのまま動くが一部動かないものがある
● musl が原因で Alpine Linux で動かない場合の一般的な解決策
a. Alpine Linux をやめて Debian などを使う → コンテナサイズふえる
b. Alpine Linux の中に glibc もインストールする → めんどくさい
https://gitlab.com/dar/hugo/blob/feat-postCSS/Dockerfile
原因の調査
$ git clone https://gitlab.com/pirivan/pirivan.gitlab.io
$ cd pirivan.gitlab.io
$ git checkout development
$ docker run --rm -it -v $PWD:/src --workdir /src registry.gitlab.com/pages/hugo/hugo_extended /bin/sh
/src # hugo
Building sites ... Segmentation fault
まずは報告のあったサイトで hugo を動かしてみる
gdb による調査
$ docker run --rm -it -v $PWD:/src --workdir /src --privileged 
registry.gitlab.com/pages/hugo/hugo_extended /bin/sh
/src # apk add gdb
/src # gdb hugo
(gdb) run
Starting program: /usr/bin/hugo
[New LWP 15]
[New LWP 16]
[New LWP 17]
[New LWP 18]
[New LWP 19]
[New LWP 20]
[New LWP 21]
Building sites … [New LWP 22]
[New LWP 23]
[New LWP 24]
[New LWP 25]
[New LWP 26]
次にデバッガで hugo を動かしてみる
gdb による調査
Thread 6 "hugo" received signal SIGSEGV, Segmentation fault.
[Switching to LWP 19]
0x0000000000f5807e in Sass::Parser::parse_expression() ()
(gdb) info threads
Id Target Id Frame
1 LWP 11 "hugo" 0x00000000004e63e3 in ?? ()
2 LWP 15 "hugo" 0x00000000004e5e4d in ?? ()
3 LWP 16 "hugo" 0x00000000004e63e3 in ?? ()
4 LWP 17 "hugo" 0x00000000004e63e3 in ?? ()
5 LWP 18 "hugo" 0x00000000004e63e3 in ?? ()
* 6 LWP 19 "hugo" 0x0000000000f5807e in Sass::Parser::parse_expression() ()
7 LWP 20 "hugo" 0x00000000004e63e3 in ?? ()
8 LWP 21 "hugo" 0x00000000004e63e3 in ?? ()
9 LWP 22 "hugo" 0x00000000004e63e3 in ?? ()
10 LWP 23 "hugo" 0x00000000004e63e3 in ?? ()
11 LWP 24 "hugo" 0x00000000004e63e3 in ?? ()
12 LWP 25 "hugo" 0x00000000004e63e3 in ?? ()
13 LWP 26 "hugo" 0x00000000004e63e3 in ?? ()
スレッドのひとつが libsass 関数の中で SIGSEGV
gdb による調査
(gdb) bt
#0 0x0000000000f5807e in Sass::Parser::parse_expression() ()
#1 0x0000000000f59520 in Sass::Parser::parse_relation() ()
#2 0x0000000000f5a7c0 in Sass::Parser::parse_conjunction() ()
...
...
#90 0x0000000000f94988 in sass_compiler_parse ()
#91 0x0000000000ea0f87 in _cgo_a9af2a58ca08_Cfunc_sass_compiler_parse ()
#92 0x00000000004e3d10 in ?? ()
#93 0x0000000001ea6100 in __bss_start ()
#94 0x0000000000000001 in ?? ()
#95 0x0000000001ec0006 in __bss_start ()
#96 0x00007ffff5a221f0 in ?? ()
#97 0x000000c000fecee8 in ?? ()
#98 0x0000000000002b40 in ?? ()
#99 0x000000c000001e00 in ?? ()
#100 0x00000000004b9690 in ?? ()
#101 0x0000000000000000 in ?? ()
スタックが深い... これはスタックオーバーフロー?
musl スレッドスタックサイズ
Thread stack size
The default stack size for new threads on glibc is determined
based on the resource limit governing the main thread’s stack
(RLIMIT_STACK). It generally ends up being 2-10 MB.
musl provides a default stack size of 80k. This does not
include the guard page, nor does it include the space used for
TLS unless total TLS size is very small. So the actual map size
may appear closer to 90k, with around 80k usable by the
application. This size was determined empirically with the goals of
not gratuitously breaking applications but also not causing large
amounts of memory and virtual address space to be committed in
programs with large numbers of threads. Programs needing
larger stacks, or which explicitly want a smaller stack, should
make this explicit with pthread_attr_setstacksize. For largely
unrestrained use of the standard library, a minimum of 12k is
recommended, but stack sizes down to 2k are allowed.
https://wiki.musl-libc.org/functional-differences-from-glibc.html
● muslはスレッドに対して極端に少ない
スタックを割り当てる
● 80KBと書いてあるが現在は128KBに
増量されている
● 解決方法はスレッドを作る前に
pthread_attr_setstacksize() などでス
タックサイズを増やすこと
● Ruby・Python含む様々なプロジェクト
がmuslのスタックオーバーフローに辛
酸を舐めさせられている
● Goではlibsassのような外部ライブラリ
を呼び出すときに問題になる
解決策の模索
● Go 言語のランタイムライブラリや Hugo を修正するのは難しい
● なんとかスタックサイズをランタイムで増加させられないか、muslのコードを読み始
める
● だいたいは DEFAULT_STACK_SIZE といった定数にハードコードされているのだが、
ELFダイナミックリンカであやしげなコードを発見
} else if (ph->p_type == PT_GNU_STACK) {
if (!runtime && ph->p_memsz > __default_stacksize) {
__default_stacksize =
ph->p_memsz < DEFAULT_STACK_MAX ?
ph->p_memsz : DEFAULT_STACK_MAX;
}
}
http://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c#n635
musl 新機能の発見
support setting of default thread stack size via
PT_GNU_STACK header
this facilitates building software that assumes a large default
stack size without any patching to call pthread_setattr_default_np
or pthread_attr_setstacksize at each thread creation site, using
just LDFLAGS.
normally the PT_GNU_STACK header is used only to reflect
whether executable stack is desired, but with GNU ld at least,
passing -Wl,-z,stack-size=N will set a size on the program header.
with this patch, that size will be incorporated into the default
stack size (subject to increase-only rule and
DEFAULT_STACK_MAX limit).
http://git.musl-libc.org/cgit/musl/commit/?id=7b3348a98c139b4
b4238384e52d4b0eb237e4833
● なんと ELF のプログラムヘッダの
PT_GNU_STACK セクションのサイズで
デフォルトスタックサイズを変更できる
機能が追加されていることがわかった
(ELF = Linux などで使われる実行ファ
イルの形式のこと)
● リンク時のオプションで
-Wl,-z,stack-size=N のように設
定することが前提だが…
● 実行ファイルしかなくても ELF プログラ
ムヘッダにバイナリパッチできればス
タックサイズは増やせる!
Hugo Extended 実行ファイル (Linux amd64) のプログラムヘッダ
$ objdump -p hugo
hugo: file format ELF64-x86-64
Program Header:
PHDR off 0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
filesz 0x0000000000000230 memsz 0x0000000000000230 flags r-x
INTERP off 0x0000000000000270 vaddr 0x0000000000400270 paddr 0x0000000000400270 align 2**0
filesz 0x000000000000001c memsz 0x000000000000001c flags r--
LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
filesz 0x00000000018266da memsz 0x00000000018266da flags r-x
LOAD off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**21
filesz 0x0000000000074801 memsz 0x00000000000a7718 flags rw-
DYNAMIC off 0x0000000001830cf0 vaddr 0x0000000001e30cf0 paddr 0x0000000001e30cf0 align 2**3
filesz 0x0000000000000220 memsz 0x0000000000000220 flags rw-
NOTE off 0x000000000000028c vaddr 0x000000000040028c paddr 0x000000000040028c align 2**2
filesz 0x00000000000000a8 memsz 0x00000000000000a8 flags r--
TLS off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**3
filesz 0x0000000000000000 memsz 0x0000000000000008 flags r--
EH_FRAME off 0x00000000017e30fc vaddr 0x0000000001be30fc paddr 0x0000000001be30fc align 2**2
filesz 0x00000000000079b4 memsz 0x00000000000079b4 flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
RELRO off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**0
filesz 0x000000000000a1a0 memsz 0x000000000000a1a0 flags r--
この memsz を
書き換えたい
こっちは execstack(8)
で書き換え可能
PT_GNU_STACK
is これ
Go 言語 debug/elf でバイナリパッチ
debug/elf は ELF オブジェクトファイルを操作するためのパッケージ
● https://golang.org/pkg/debug/elf/
● ELF ヘッダ、プログラムヘッダの struct や各種定数の定義がある
● encoding/binary と組み合わせて使うことができる
● 標準パッケージでこういうことができる Go 言語は非常にすばらしい
muslstack
Binary patch utility to set default thread stack size for musl libc
● https://github.com/yaegashi/muslstack
● Go 言語の debug/elf を利用した ELF ヘッダ書き換えユーティリティ
● PT_GNU_STACK ヘッダが対象という点で execstack(8) に類似するツール
● 様々な Linux ELF 実行ファイルに対応
○ 32-bit / 64-bit
○ little endian / big endian
○ x86, x86-64, arm, arm64, etc.
● 効果を確認できるテストケースあり
func patch(path string, setStackSize bool, stackSize uint64) (uint64, error)
switch fh.Class {
case elf.ELFCLASS32:
eh := &elf.Header32{}
if err := binary.Read(f, fh.ByteOrder, eh); err != nil {
return 0, err
}
phoff := int64(eh.Phoff)
phentsize := int64(eh.Phentsize)
phnum := int(eh.Phnum)
for i := 0; i < phnum; i++ {
off := phoff + int64(i)*phentsize
f.Seek(off, io.SeekStart)
ph := &elf.Prog32{}
if err := binary.Read(f, fh.ByteOrder, ph); err != nil {
return 0, err
}
if ph.Type == ptGnuStack {
if setStackSize {
ph.Memsz = uint32(stackSize)
f.Seek(off, io.SeekStart)
if err := binary.Write(f, fh.ByteOrder, ph); err != nil {
return 0, err
}
}
return uint64(ph.Memsz), nil
}
}
https://github.com/yaegashi/muslstack/blob/master/main.go
Dockerfile での muslstack 利用例
FROM golang:1.12-alpine
ARG HUGO=hugo
ARG HUGO_VERSION=0.55.6
ARG HUGO_SHA=39d3119cdb9ba5d6f1f1b43693e707937ce851791a2ea8d28003f49927c428f4
ARG HUGO_EXTENDED_SHA=8962b8cdc0ca220da97293cea0bb1b31718cb4d99d0766be6865cb976b1c1805
RUN set -eux && 
case ${HUGO} in *_extended) HUGO_SHA="${HUGO_EXTENDED_SHA}" ;; esac && 
apk add --update --no-cache ca-certificates openssl git && 
wget -O ${HUGO_VERSION}.tar.gz 
https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/${HUGO}_${HUGO_VERSION}_Linux-64bit.tar.gz && 
echo "${HUGO_SHA} ${HUGO_VERSION}.tar.gz" | sha256sum -c && 
tar xf ${HUGO_VERSION}.tar.gz && mv hugo* /usr/bin/hugo
RUN go get github.com/yaegashi/muslstack
RUN muslstack -s 0x800000 /usr/bin/hugo
FROM alpine:edge
ARG HUGO=hugo
COPY --from=0 /usr/bin/hugo /usr/bin
RUN set -eux && 
...
muslstackでhugo
実行ファイルを修正
alpine:edge でないと
効果がないので注意
マルチステージビルドで活用
余談
alpine:edge だと Hugo Extended がなかなか落ちてくれない
● musl デフォルトスタックが 80KB→128KB に増えたから?
● SCSS 版 Ackermann 関数を食わせてようやく半々の確率で落ちる
/usr/bin/hugo: stackSize: 0x800000
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000800000 flags rw-
Building sites ... ERROR 2019/06/16 14:22:30 error: failed to transform resource: SCSS processi
ng failed: file "stdin", line 6, col 25: Stack depth exceeded max of 1024
Error: Error building site: logged 1 error(s)
Total in 2372 ms
/usr/bin/hugo: stackSize: 0x0
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
Building sites ... Segmentation fault
まとめ
Hugo Extended
Alpine Linux (musl libc) スタックサイズ問題
musl libc 新機能 PT_GNU_STACK ヘッダでスタックサイズ設定
Go 言語 debug/elf パッケージ
https://github.com/yaegashi/muslstack
おわり
Alpine Linux (musl libc) コンテナで動かないプログラムにお悩みの方は
muslstack と alpine:edge を試してみてください!

Weitere ähnliche Inhalte

Was ist angesagt?

hpingで作るパケット
hpingで作るパケットhpingで作るパケット
hpingで作るパケットTakaaki Hoyo
 
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Kazuhiro Takahashi
 
謎の言語Forthが謎なので実装した
謎の言語Forthが謎なので実装した謎の言語Forthが謎なので実装した
謎の言語Forthが謎なので実装したt-sin
 
Trema day 1
Trema day 1Trema day 1
Trema day 1ykuga
 
Varnishのログの眺め方
Varnishのログの眺め方Varnishのログの眺め方
Varnishのログの眺め方Iwana Chan
 
仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題に仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題にmagoroku Yamamoto
 
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)Iwana Chan
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたことMITSUNARI Shigeo
 
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくばHirotaka Kawata
 
あるmmapの話
あるmmapの話あるmmapの話
あるmmapの話nullnilaki
 
パケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapパケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapfurandon_pig
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングKiwamu Okabe
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell scriptMasami Hiramatsu
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺MITSUNARI Shigeo
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenMITSUNARI Shigeo
 

Was ist angesagt? (20)

hpingで作るパケット
hpingで作るパケットhpingで作るパケット
hpingで作るパケット
 
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
 
謎の言語Forthが謎なので実装した
謎の言語Forthが謎なので実装した謎の言語Forthが謎なので実装した
謎の言語Forthが謎なので実装した
 
Trema day 1
Trema day 1Trema day 1
Trema day 1
 
Varnishのログの眺め方
Varnishのログの眺め方Varnishのログの眺め方
Varnishのログの眺め方
 
仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題に仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題に
 
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
 
Ras piでrt linux
Ras piでrt linuxRas piでrt linux
Ras piでrt linux
 
Altanative macro
Altanative macroAltanative macro
Altanative macro
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと
 
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
 
あるmmapの話
あるmmapの話あるmmapの話
あるmmapの話
 
V6 unix vol.2 in okinawa
V6 unix vol.2 in okinawaV6 unix vol.2 in okinawa
V6 unix vol.2 in okinawa
 
Memory sanitizer
Memory sanitizerMemory sanitizer
Memory sanitizer
 
about Tcpreplay
about Tcpreplayabout Tcpreplay
about Tcpreplay
 
パケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapパケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmap
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell script
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
 

Ähnlich wie golang binary hacks

Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2tamtam180
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)tamtam180
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法博文 斉藤
 
mbedではじめる組み込みHaskellプログラミング
mbedではじめる組み込みHaskellプログラミングmbedではじめる組み込みHaskellプログラミング
mbedではじめる組み込みHaskellプログラミングKiwamu Okabe
 
Hadoop splittable-lzo-compression
Hadoop splittable-lzo-compressionHadoop splittable-lzo-compression
Hadoop splittable-lzo-compressionDaiki Sato
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...Netwalker lab kapper
 
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築yaegashi
 
EmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよEmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよKiwamu Okabe
 
C83 λカ娘の販促にやってきました
C83 λカ娘の販促にやってきましたC83 λカ娘の販促にやってきました
C83 λカ娘の販促にやってきましたKiwamu Okabe
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!Yohei Fushii
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code readingHiro Yoshioka
 
今最もアツイdistribution Gentoo Linuxについて
今最もアツイdistribution Gentoo Linuxについて今最もアツイdistribution Gentoo Linuxについて
今最もアツイdistribution Gentoo LinuxについてTakuto Matsuu
 
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Mori Shingo
 

Ähnlich wie golang binary hacks (20)

Yesod on Heroku
Yesod on HerokuYesod on Heroku
Yesod on Heroku
 
R3.0.0 is relased
R3.0.0 is relasedR3.0.0 is relased
R3.0.0 is relased
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
 
mbedではじめる組み込みHaskellプログラミング
mbedではじめる組み込みHaskellプログラミングmbedではじめる組み込みHaskellプログラミング
mbedではじめる組み込みHaskellプログラミング
 
Hadoop splittable-lzo-compression
Hadoop splittable-lzo-compressionHadoop splittable-lzo-compression
Hadoop splittable-lzo-compression
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...
はじめての超格安2,500円 Nexus7 2012改造と Android7.1.2 AOSP、postmarketOS in 2020 Beginner...
 
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築
JTF2020 クロスコンパイルだけが能ではない組み込みLinuxシステムのCI/CDインフラ構築
 
EmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよEmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよ
 
C83 λカ娘の販促にやってきました
C83 λカ娘の販促にやってきましたC83 λカ娘の販促にやってきました
C83 λカ娘の販促にやってきました
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code reading
 
about dakota6.7 gui
about dakota6.7 guiabout dakota6.7 gui
about dakota6.7 gui
 
今最もアツイdistribution Gentoo Linuxについて
今最もアツイdistribution Gentoo Linuxについて今最もアツイdistribution Gentoo Linuxについて
今最もアツイdistribution Gentoo Linuxについて
 
Code Pack の話
Code Pack の話Code Pack の話
Code Pack の話
 
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋
 

Mehr von yaegashi

Terraforming Windows Virtual Desktop Infrastructure on Azure
Terraforming Windows Virtual Desktop Infrastructure on AzureTerraforming Windows Virtual Desktop Infrastructure on Azure
Terraforming Windows Virtual Desktop Infrastructure on Azureyaegashi
 
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CD
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CDAzure DevOps で実現する Unity アプリのハイパフォーマンス CI/CD
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CDyaegashi
 
Customazed CLI: カスタムVMイメージ作成支援ツール
Customazed CLI: カスタムVMイメージ作成支援ツールCustomazed CLI: カスタムVMイメージ作成支援ツール
Customazed CLI: カスタムVMイメージ作成支援ツールyaegashi
 
Goで作って配布するAzureコマンドラインユーティリティ
Goで作って配布するAzureコマンドラインユーティリティGoで作って配布するAzureコマンドラインユーティリティ
Goで作って配布するAzureコマンドラインユーティリティyaegashi
 
msgraph: Terraform provider for Microsoft Graph
msgraph: Terraform provider for Microsoft Graphmsgraph: Terraform provider for Microsoft Graph
msgraph: Terraform provider for Microsoft Graphyaegashi
 
go generate 完全入門
go generate 完全入門go generate 完全入門
go generate 完全入門yaegashi
 
msgraph.go: Go言語で Microsoft Graph プログラミング
msgraph.go: Go言語で Microsoft Graph プログラミングmsgraph.go: Go言語で Microsoft Graph プログラミング
msgraph.go: Go言語で Microsoft Graph プログラミングyaegashi
 
AnsibleでAzureの インフラを管理する話 + α
AnsibleでAzureの インフラを管理する話 + αAnsibleでAzureの インフラを管理する話 + α
AnsibleでAzureの インフラを管理する話 + αyaegashi
 
msgraph-sshpubkey
msgraph-sshpubkeymsgraph-sshpubkey
msgraph-sshpubkeyyaegashi
 
Microsoft Graph API Library for Go
Microsoft Graph API Library for GoMicrosoft Graph API Library for Go
Microsoft Graph API Library for Goyaegashi
 
Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話yaegashi
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件yaegashi
 
Ansible モジュール 作成・配布・貢献
Ansible モジュール 作成・配布・貢献Ansible モジュール 作成・配布・貢献
Ansible モジュール 作成・配布・貢献yaegashi
 

Mehr von yaegashi (13)

Terraforming Windows Virtual Desktop Infrastructure on Azure
Terraforming Windows Virtual Desktop Infrastructure on AzureTerraforming Windows Virtual Desktop Infrastructure on Azure
Terraforming Windows Virtual Desktop Infrastructure on Azure
 
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CD
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CDAzure DevOps で実現する Unity アプリのハイパフォーマンス CI/CD
Azure DevOps で実現する Unity アプリのハイパフォーマンス CI/CD
 
Customazed CLI: カスタムVMイメージ作成支援ツール
Customazed CLI: カスタムVMイメージ作成支援ツールCustomazed CLI: カスタムVMイメージ作成支援ツール
Customazed CLI: カスタムVMイメージ作成支援ツール
 
Goで作って配布するAzureコマンドラインユーティリティ
Goで作って配布するAzureコマンドラインユーティリティGoで作って配布するAzureコマンドラインユーティリティ
Goで作って配布するAzureコマンドラインユーティリティ
 
msgraph: Terraform provider for Microsoft Graph
msgraph: Terraform provider for Microsoft Graphmsgraph: Terraform provider for Microsoft Graph
msgraph: Terraform provider for Microsoft Graph
 
go generate 完全入門
go generate 完全入門go generate 完全入門
go generate 完全入門
 
msgraph.go: Go言語で Microsoft Graph プログラミング
msgraph.go: Go言語で Microsoft Graph プログラミングmsgraph.go: Go言語で Microsoft Graph プログラミング
msgraph.go: Go言語で Microsoft Graph プログラミング
 
AnsibleでAzureの インフラを管理する話 + α
AnsibleでAzureの インフラを管理する話 + αAnsibleでAzureの インフラを管理する話 + α
AnsibleでAzureの インフラを管理する話 + α
 
msgraph-sshpubkey
msgraph-sshpubkeymsgraph-sshpubkey
msgraph-sshpubkey
 
Microsoft Graph API Library for Go
Microsoft Graph API Library for GoMicrosoft Graph API Library for Go
Microsoft Graph API Library for Go
 
Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
Ansible モジュール 作成・配布・貢献
Ansible モジュール 作成・配布・貢献Ansible モジュール 作成・配布・貢献
Ansible モジュール 作成・配布・貢献
 

Kürzlich hochgeladen

自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 

Kürzlich hochgeladen (8)

自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 

golang binary hacks

  • 1. golang binary hacks 2019-06-18 Takeshi Yaegashi golang.tokyo #25
  • 2. 自己紹介 八重樫 剛史 Takeshi Yaegashi ● 株式会社バンダイナムコスタジオ所属 ● Linux・Unix・OSS・低レベルなことが好きなエンジニア ● もちろん Go 言語も大好きです! ● Go を使ったお仕事 ○ IoT 案件の Raspberry Pi 制御プログラム ○ スマホゲームアプリのサーバ
  • 4. Hugo Hugo は Go 言語で書かれた静的サイトジェネレータ ● https://gohugo.io ● Hugo には 2 種類あり、それぞれのバイナリが配布されている ○ Hugo ■ 基本機能のみの Hugo ○ Hugo Extended ■ SASS/SCSS のアセット処理もできる拡張版 Hugo ■ C++ で書かれたライブラリ libsass を組み込んでいる (cgo)
  • 5. Hugo Extended on Docker 先日 gitlab.com/pages/hugo に対してコントリビュートした ● https://gitlab.com/pages/hugo/merge_requests/83 ● プロジェクト Docker レジストリに hugo_extended イメージを追加 ○ registry.gitlab.com/pages/hugo/hugo ○ registry.gitlab.com/pages/hugo/hugo_extended ● GitHub の Release からビルドされたバイナリをダウンロードして Alpine Linux のコンテナで動かす、よくある構成
  • 6. Hugo Extended on Alpine Linux その後 hugo_extended イメージが動かないという報告がきた ● https://gitlab.com/pages/hugo/issues/31 ● 複雑な SCSS を含むサイトで Segmentation fault が起きるらしい ● 同じ問題を抱えている人が結構多いらしい ○ Alpine Linux を使っているとだめ ○ musl libc だと動かない glibc だと動く
  • 7. musl libc musl は glibc と ABI 互換性のある Linux 用軽量 C ランタイムライブラリ ● https://www.musl-libc.org ● コンテナ容量削減の目的で Alpine Linux などで使われている ● glibc でビルドした実行ファイルがそのまま動くが一部動かないものがある ● musl が原因で Alpine Linux で動かない場合の一般的な解決策 a. Alpine Linux をやめて Debian などを使う → コンテナサイズふえる b. Alpine Linux の中に glibc もインストールする → めんどくさい https://gitlab.com/dar/hugo/blob/feat-postCSS/Dockerfile
  • 8. 原因の調査 $ git clone https://gitlab.com/pirivan/pirivan.gitlab.io $ cd pirivan.gitlab.io $ git checkout development $ docker run --rm -it -v $PWD:/src --workdir /src registry.gitlab.com/pages/hugo/hugo_extended /bin/sh /src # hugo Building sites ... Segmentation fault まずは報告のあったサイトで hugo を動かしてみる
  • 9. gdb による調査 $ docker run --rm -it -v $PWD:/src --workdir /src --privileged registry.gitlab.com/pages/hugo/hugo_extended /bin/sh /src # apk add gdb /src # gdb hugo (gdb) run Starting program: /usr/bin/hugo [New LWP 15] [New LWP 16] [New LWP 17] [New LWP 18] [New LWP 19] [New LWP 20] [New LWP 21] Building sites … [New LWP 22] [New LWP 23] [New LWP 24] [New LWP 25] [New LWP 26] 次にデバッガで hugo を動かしてみる
  • 10. gdb による調査 Thread 6 "hugo" received signal SIGSEGV, Segmentation fault. [Switching to LWP 19] 0x0000000000f5807e in Sass::Parser::parse_expression() () (gdb) info threads Id Target Id Frame 1 LWP 11 "hugo" 0x00000000004e63e3 in ?? () 2 LWP 15 "hugo" 0x00000000004e5e4d in ?? () 3 LWP 16 "hugo" 0x00000000004e63e3 in ?? () 4 LWP 17 "hugo" 0x00000000004e63e3 in ?? () 5 LWP 18 "hugo" 0x00000000004e63e3 in ?? () * 6 LWP 19 "hugo" 0x0000000000f5807e in Sass::Parser::parse_expression() () 7 LWP 20 "hugo" 0x00000000004e63e3 in ?? () 8 LWP 21 "hugo" 0x00000000004e63e3 in ?? () 9 LWP 22 "hugo" 0x00000000004e63e3 in ?? () 10 LWP 23 "hugo" 0x00000000004e63e3 in ?? () 11 LWP 24 "hugo" 0x00000000004e63e3 in ?? () 12 LWP 25 "hugo" 0x00000000004e63e3 in ?? () 13 LWP 26 "hugo" 0x00000000004e63e3 in ?? () スレッドのひとつが libsass 関数の中で SIGSEGV
  • 11. gdb による調査 (gdb) bt #0 0x0000000000f5807e in Sass::Parser::parse_expression() () #1 0x0000000000f59520 in Sass::Parser::parse_relation() () #2 0x0000000000f5a7c0 in Sass::Parser::parse_conjunction() () ... ... #90 0x0000000000f94988 in sass_compiler_parse () #91 0x0000000000ea0f87 in _cgo_a9af2a58ca08_Cfunc_sass_compiler_parse () #92 0x00000000004e3d10 in ?? () #93 0x0000000001ea6100 in __bss_start () #94 0x0000000000000001 in ?? () #95 0x0000000001ec0006 in __bss_start () #96 0x00007ffff5a221f0 in ?? () #97 0x000000c000fecee8 in ?? () #98 0x0000000000002b40 in ?? () #99 0x000000c000001e00 in ?? () #100 0x00000000004b9690 in ?? () #101 0x0000000000000000 in ?? () スタックが深い... これはスタックオーバーフロー?
  • 12. musl スレッドスタックサイズ Thread stack size The default stack size for new threads on glibc is determined based on the resource limit governing the main thread’s stack (RLIMIT_STACK). It generally ends up being 2-10 MB. musl provides a default stack size of 80k. This does not include the guard page, nor does it include the space used for TLS unless total TLS size is very small. So the actual map size may appear closer to 90k, with around 80k usable by the application. This size was determined empirically with the goals of not gratuitously breaking applications but also not causing large amounts of memory and virtual address space to be committed in programs with large numbers of threads. Programs needing larger stacks, or which explicitly want a smaller stack, should make this explicit with pthread_attr_setstacksize. For largely unrestrained use of the standard library, a minimum of 12k is recommended, but stack sizes down to 2k are allowed. https://wiki.musl-libc.org/functional-differences-from-glibc.html ● muslはスレッドに対して極端に少ない スタックを割り当てる ● 80KBと書いてあるが現在は128KBに 増量されている ● 解決方法はスレッドを作る前に pthread_attr_setstacksize() などでス タックサイズを増やすこと ● Ruby・Python含む様々なプロジェクト がmuslのスタックオーバーフローに辛 酸を舐めさせられている ● Goではlibsassのような外部ライブラリ を呼び出すときに問題になる
  • 13. 解決策の模索 ● Go 言語のランタイムライブラリや Hugo を修正するのは難しい ● なんとかスタックサイズをランタイムで増加させられないか、muslのコードを読み始 める ● だいたいは DEFAULT_STACK_SIZE といった定数にハードコードされているのだが、 ELFダイナミックリンカであやしげなコードを発見 } else if (ph->p_type == PT_GNU_STACK) { if (!runtime && ph->p_memsz > __default_stacksize) { __default_stacksize = ph->p_memsz < DEFAULT_STACK_MAX ? ph->p_memsz : DEFAULT_STACK_MAX; } } http://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c#n635
  • 14. musl 新機能の発見 support setting of default thread stack size via PT_GNU_STACK header this facilitates building software that assumes a large default stack size without any patching to call pthread_setattr_default_np or pthread_attr_setstacksize at each thread creation site, using just LDFLAGS. normally the PT_GNU_STACK header is used only to reflect whether executable stack is desired, but with GNU ld at least, passing -Wl,-z,stack-size=N will set a size on the program header. with this patch, that size will be incorporated into the default stack size (subject to increase-only rule and DEFAULT_STACK_MAX limit). http://git.musl-libc.org/cgit/musl/commit/?id=7b3348a98c139b4 b4238384e52d4b0eb237e4833 ● なんと ELF のプログラムヘッダの PT_GNU_STACK セクションのサイズで デフォルトスタックサイズを変更できる 機能が追加されていることがわかった (ELF = Linux などで使われる実行ファ イルの形式のこと) ● リンク時のオプションで -Wl,-z,stack-size=N のように設 定することが前提だが… ● 実行ファイルしかなくても ELF プログラ ムヘッダにバイナリパッチできればス タックサイズは増やせる!
  • 15. Hugo Extended 実行ファイル (Linux amd64) のプログラムヘッダ $ objdump -p hugo hugo: file format ELF64-x86-64 Program Header: PHDR off 0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3 filesz 0x0000000000000230 memsz 0x0000000000000230 flags r-x INTERP off 0x0000000000000270 vaddr 0x0000000000400270 paddr 0x0000000000400270 align 2**0 filesz 0x000000000000001c memsz 0x000000000000001c flags r-- LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21 filesz 0x00000000018266da memsz 0x00000000018266da flags r-x LOAD off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**21 filesz 0x0000000000074801 memsz 0x00000000000a7718 flags rw- DYNAMIC off 0x0000000001830cf0 vaddr 0x0000000001e30cf0 paddr 0x0000000001e30cf0 align 2**3 filesz 0x0000000000000220 memsz 0x0000000000000220 flags rw- NOTE off 0x000000000000028c vaddr 0x000000000040028c paddr 0x000000000040028c align 2**2 filesz 0x00000000000000a8 memsz 0x00000000000000a8 flags r-- TLS off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**3 filesz 0x0000000000000000 memsz 0x0000000000000008 flags r-- EH_FRAME off 0x00000000017e30fc vaddr 0x0000000001be30fc paddr 0x0000000001be30fc align 2**2 filesz 0x00000000000079b4 memsz 0x00000000000079b4 flags r-- STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- RELRO off 0x0000000001826e60 vaddr 0x0000000001e26e60 paddr 0x0000000001e26e60 align 2**0 filesz 0x000000000000a1a0 memsz 0x000000000000a1a0 flags r-- この memsz を 書き換えたい こっちは execstack(8) で書き換え可能 PT_GNU_STACK is これ
  • 16. Go 言語 debug/elf でバイナリパッチ debug/elf は ELF オブジェクトファイルを操作するためのパッケージ ● https://golang.org/pkg/debug/elf/ ● ELF ヘッダ、プログラムヘッダの struct や各種定数の定義がある ● encoding/binary と組み合わせて使うことができる ● 標準パッケージでこういうことができる Go 言語は非常にすばらしい
  • 17. muslstack Binary patch utility to set default thread stack size for musl libc ● https://github.com/yaegashi/muslstack ● Go 言語の debug/elf を利用した ELF ヘッダ書き換えユーティリティ ● PT_GNU_STACK ヘッダが対象という点で execstack(8) に類似するツール ● 様々な Linux ELF 実行ファイルに対応 ○ 32-bit / 64-bit ○ little endian / big endian ○ x86, x86-64, arm, arm64, etc. ● 効果を確認できるテストケースあり
  • 18. func patch(path string, setStackSize bool, stackSize uint64) (uint64, error) switch fh.Class { case elf.ELFCLASS32: eh := &elf.Header32{} if err := binary.Read(f, fh.ByteOrder, eh); err != nil { return 0, err } phoff := int64(eh.Phoff) phentsize := int64(eh.Phentsize) phnum := int(eh.Phnum) for i := 0; i < phnum; i++ { off := phoff + int64(i)*phentsize f.Seek(off, io.SeekStart) ph := &elf.Prog32{} if err := binary.Read(f, fh.ByteOrder, ph); err != nil { return 0, err } if ph.Type == ptGnuStack { if setStackSize { ph.Memsz = uint32(stackSize) f.Seek(off, io.SeekStart) if err := binary.Write(f, fh.ByteOrder, ph); err != nil { return 0, err } } return uint64(ph.Memsz), nil } } https://github.com/yaegashi/muslstack/blob/master/main.go
  • 19. Dockerfile での muslstack 利用例 FROM golang:1.12-alpine ARG HUGO=hugo ARG HUGO_VERSION=0.55.6 ARG HUGO_SHA=39d3119cdb9ba5d6f1f1b43693e707937ce851791a2ea8d28003f49927c428f4 ARG HUGO_EXTENDED_SHA=8962b8cdc0ca220da97293cea0bb1b31718cb4d99d0766be6865cb976b1c1805 RUN set -eux && case ${HUGO} in *_extended) HUGO_SHA="${HUGO_EXTENDED_SHA}" ;; esac && apk add --update --no-cache ca-certificates openssl git && wget -O ${HUGO_VERSION}.tar.gz https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/${HUGO}_${HUGO_VERSION}_Linux-64bit.tar.gz && echo "${HUGO_SHA} ${HUGO_VERSION}.tar.gz" | sha256sum -c && tar xf ${HUGO_VERSION}.tar.gz && mv hugo* /usr/bin/hugo RUN go get github.com/yaegashi/muslstack RUN muslstack -s 0x800000 /usr/bin/hugo FROM alpine:edge ARG HUGO=hugo COPY --from=0 /usr/bin/hugo /usr/bin RUN set -eux && ... muslstackでhugo 実行ファイルを修正 alpine:edge でないと 効果がないので注意 マルチステージビルドで活用
  • 20. 余談 alpine:edge だと Hugo Extended がなかなか落ちてくれない ● musl デフォルトスタックが 80KB→128KB に増えたから? ● SCSS 版 Ackermann 関数を食わせてようやく半々の確率で落ちる /usr/bin/hugo: stackSize: 0x800000 STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000800000 flags rw- Building sites ... ERROR 2019/06/16 14:22:30 error: failed to transform resource: SCSS processi ng failed: file "stdin", line 6, col 25: Stack depth exceeded max of 1024 Error: Error building site: logged 1 error(s) Total in 2372 ms /usr/bin/hugo: stackSize: 0x0 STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- Building sites ... Segmentation fault
  • 21. まとめ Hugo Extended Alpine Linux (musl libc) スタックサイズ問題 musl libc 新機能 PT_GNU_STACK ヘッダでスタックサイズ設定 Go 言語 debug/elf パッケージ https://github.com/yaegashi/muslstack
  • 22. おわり Alpine Linux (musl libc) コンテナで動かないプログラムにお悩みの方は muslstack と alpine:edge を試してみてください!