Libseccomp: 버그: gen_bpf_generate()κ°€ μ‹€νŒ¨λ₯Ό μ œλŒ€λ‘œ μ²˜λ¦¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2020λ…„ 05μ›” 28일  Β·  15μ½”λ©˜νŠΈ  Β·  좜처: seccomp/libseccomp

μ•ˆλ…•,

μš°μ„ , libseccomp에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. μš°λ¦¬λŠ” μ§€κΈˆκΉŒμ§€ λͺ‡ λ…„ λ™μ•ˆ ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œ ν–‰λ³΅ν•˜κ²Œ μ‚¬μš©ν–ˆμœΌλ©° μ–΄λ–€ λ¬Έμ œλ„ λ°œμƒν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€(μ§€κΈˆκΉŒμ§€). 이것이 우리 μ½”λ“œμ˜ 버그인지, λ¬Έμ„œμ— λŒ€ν•œ μ˜€ν•΄μΈμ§€, μ•„λ‹ˆλ©΄ λ‹€λ₯Έ 것인지 ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ§€λ‚œ ν•œ 달 λ™μ•ˆ 이것을 μΆ”μ ν•˜λ €κ³  λ…Έλ ₯ν–ˆμ§€λ§Œ 아무 μ†Œμš©μ΄ μ—†μ—ˆμŠ΅λ‹ˆλ‹€.

μ΅œκ·Όμ— libseccomp 2.3.3(Debian μ•ˆμ • μ €μž₯μ†Œ 버전)μ—μ„œ 2.4.3으둜의 μ—…κ·Έλ ˆμ΄λ“œκ°€ ν¬ν•¨λœ Docker μ»¨ν…Œμ΄λ„ˆμ˜ νŒ¨ν‚€μ§€λ₯Ό μ—…κ·Έλ ˆμ΄λ“œν–ˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ μ‹œμŠ€ν…œ νŒ¨ν‚€μ§€λ„ μ—…κ·Έλ ˆμ΄λ“œλ˜μ—ˆμ§€λ§Œ κΈ°λ‘ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 우리 컀널은 μ—…κ·Έλ ˆμ΄λ“œλ˜μ§€ μ•Šμ•˜μœΌλ©° 버전은 4.19.0-8-amd64μž…λ‹ˆλ‹€.

μš°λ¦¬λŠ” SCMP_ACT_TRACE λ₯Ό μ‚¬μš©ν•˜κ³  libseccomp의 μ˜μ‚¬ λ²ˆν˜Έκ°€ μ•„λ‹Œ κΈ°λ³Έ μ‹œμŠ€ν…œ 호좜 번호λ₯Ό μ‚¬μš©ν•˜μ—¬ μΆ”κ°€λœ SCMP_ACT_ALLOW κ·œμΉ™λ§ŒμœΌλ‘œ κ΅¬μ„±λœ ν•„ν„°λ₯Ό λΉŒλ“œν•©λ‹ˆλ‹€. exec 전에 seccomp ν•„ν„°λ₯Ό λΉŒλ“œν•˜κ³  λ‘œλ“œν•˜λŠ” 64λΉ„νŠΈ λ„μš°λ―Έ ν”„λ‘œμ„ΈμŠ€λ₯Ό λΆ„κΈ°ν•˜μ—¬ λ‹€λ₯Έ 64λΉ„νŠΈ λ°”μ΄λ„ˆλ¦¬λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

참고둜 이것은 seccomp_rule_add 맀뉴얼 νŽ˜μ΄μ§€ 와 μœ μ‚¬ν•œ 였λ₯˜ 검사λ₯Ό μ‚¬μš©ν•˜λŠ” seccomp μ΄ˆκΈ°ν™” ​​루틴 μ „μ²΄μž…λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ seccomp_load λŒ€ν•œ ν˜ΈμΆœμ€ 1/100,000 ν”„λ‘œμ„ΈμŠ€ μ΄ˆκΈ°ν™” 규λͺ¨μ˜ μˆœμ„œλ‘œ -EINVAL λ°˜ν™˜ν•˜κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€. (그것을 μ•ˆμ •μ μœΌλ‘œ μž¬ν˜„ν•  수 μ—†κΈ° λ•Œλ¬Έμ— λ””λ²„κ·Έν•˜κΈ°κ°€ μ§€λ£¨ν–ˆμŠ΅λ‹ˆλ‹€.) 이 μ‹œκ°„ λ™μ•ˆ 우리 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ½”λ“œ λ³€κ²½ 사항이 μ—†μ—ˆμŠ΅λ‹ˆλ‹€. 필터에 μΆ”κ°€λœ μ‹œμŠ€ν…œ ν˜ΈμΆœμ€ λͺ¨λ“  μ‹€ν–‰μ—μ„œ λ™μΌν•©λ‹ˆλ‹€.

무엇이 잘λͺ»λ  수 μžˆλŠ”μ§€(λ˜λŠ” 무엇이 잘λͺ»λ˜κ³  μžˆλŠ”μ§€ μžμ„Ένžˆ μ•Œμ•„λ³΄λŠ” 방법), λ˜λŠ” 이것이 μ–΄λ–€ μ‹μœΌλ‘œλ“  μ˜ˆμƒλ˜λŠ” κ²½μš°μ— λŒ€ν•œ 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ? μ—­λ™μ μœΌλ‘œ μ›€μ§μ΄λŠ” 뢀뢄이 λ§Žμ§€ μ•ŠμœΌλ©° λ¬Έμ„œμ—μ„œ μ™œ 이런 일이 λ°œμƒν•  수 μžˆλŠ”μ§€μ— λŒ€ν•œ λ‚΄μš©μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.

bug prioritmedium

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λΆˆν–‰νžˆλ„ 아직 μ•„λ‹™λ‹ˆλ‹€. seccomp_export_pfc 패치λ₯Ό μΆ”κ°€ν•œ ν›„ μΉ¨λ¬΅ν–ˆμŠ΅λ‹ˆλ‹€. μ–΄μ œ μ €λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμ„ λ•Œ 문제λ₯Ό μΊ‘μ²˜ν•˜κΈ° μœ„ν•΄ ν•΄λ‹Ή 패치λ₯Ό λͺ¨λ“  VM(단지 ν…ŒμŠ€νŠΈμš©μ΄ μ•„λ‹Œ)에 ν‘Έμ‹œν–ˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 침묡을 μ΄μƒν•˜κ²Œ μƒκ°ν•˜μ§€λ§Œ μ§€κΈˆμ€ λͺ¨λ“  디버깅/내보내기 논리가 seccomp_load μ‹€νŒ¨ _ν›„_ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— μš°μ—°μ˜ 일치둜 μƒκ°ν•˜κ³  μžˆμœΌλ―€λ‘œ μ‹€νŒ¨ μžμ²΄μ— 영ν–₯을 μ£Όμ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€.

λͺ¨λ“  15 λŒ“κΈ€

μ•ˆλ…•ν•˜μ„Έμš” @Xyene λ‹˜

seccomp_load() μ½”λ“œ κ²½λ‘œμ—μ„œ -EINVAL을 λ°˜ν™˜ν•˜λŠ” 곳은 λ§Žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. libseccomp v2.4.3 μ½”λ“œμ— λŒ€ν•œ λΉ λ₯Έ 검사에 λ”°λ₯΄λ©΄ 잘λͺ»λœ scmp_filter_ctx λ˜λŠ” ν•„ν„°λ₯Ό λ‘œλ“œν•˜λŠ” prctl(...) ν˜ΈμΆœμ— λŒ€ν•΄ λΆˆν‰ν•˜λŠ” 컀널 λ•Œλ¬ΈμΈ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

v2.4.3이 일반적으둜 μž‘λ™ν•˜κ³  컀널을 λ³€κ²½ν•˜μ§€ μ•Šμ€ 것을 κ³ λ €ν•˜λ©΄ prctl(...) 호좜이 μœ νš¨ν•˜μ§€ μ•Šμ€ ν•„ν„° μ»¨ν…μŠ€νŠΈλ‘œ μ΄λ„λŠ” 원인인지 μ˜μ‹¬μŠ€λŸ½μŠ΅λ‹ˆλ‹€. μ—…κ·Έλ ˆμ΄λ“œ 이후 ν”„λ‘œκ·Έλž¨μ—μ„œ λ‹€λ₯Έ μ΄μƒν•œ λ™μž‘μ„ λ°œκ²¬ν•˜μ…¨μŠ΅λ‹ˆκΉŒ? λ‹€λ₯Έ 곳에 문제λ₯Ό μΌμœΌν‚€λŠ” λ©”λͺ¨λ¦¬ 손상 λ¬Έμ œκ°€ μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

libseccomp에 였λ₯˜κ°€ μžˆμ„ 수 μžˆμ§€λ§Œ λͺ¨λ“  νšŒκ·€ ν…ŒμŠ€νŠΈμ— λŒ€ν•œ valgrind μ‹€ν–‰κ³Ό clang 및 Coverityλ₯Ό ​​λͺ¨λ‘ μ‚¬μš©ν•˜λŠ” 정적 뢄석을 ν¬ν•¨ν•˜λŠ” 일련의 검사λ₯Ό 톡해 각 릴리슀λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

λ˜ν•œ 이것은 v2.4.3μ—μ„œλŠ” 도움이 λ˜μ§€ μ•Šμ§€λ§Œ 거의 μ€€λΉ„λœ v2.5.0 λ¦΄λ¦¬μŠ€μ—μ„œ λͺ©ν‘œλ‘œ ν•˜λŠ” κ°œμ„  사항 쀑 ν•˜λ‚˜λŠ” λ¬Έμ„œν™” 및 였λ₯˜ μ½”λ“œ 처리 κ°œμ„ μž…λ‹ˆλ‹€.

μ΅œκ·Όμ— libseccomp 2.3.3(Debian μ•ˆμ • μ €μž₯μ†Œ 버전)μ—μ„œ 2.4.3으둜의 μ—…κ·Έλ ˆμ΄λ“œκ°€ ν¬ν•¨λœ Docker μ»¨ν…Œμ΄λ„ˆμ˜ νŒ¨ν‚€μ§€λ₯Ό μ—…κ·Έλ ˆμ΄λ“œν–ˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ μ‹œμŠ€ν…œ νŒ¨ν‚€μ§€λ„ μ—…κ·Έλ ˆμ΄λ“œλ˜μ—ˆμ§€λ§Œ κΈ°λ‘ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 우리 컀널은 μ—…κ·Έλ ˆμ΄λ“œλ˜μ§€ μ•Šμ•˜μœΌλ©° 버전은 4.19.0-8-amd64μž…λ‹ˆλ‹€.

μ½”λ“œμ™€ κΈ°λ³Έ 컀널이 λ³€κ²½λ˜μ§€ μ•Šμ•˜λŠ”μ§€ ν™•μΈν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. 문제λ₯Ό μΆ”μ ν•˜λŠ” 데 도움이 λ©λ‹ˆλ‹€.

참고둜 이것은 seccomp_rule_add 맀뉴얼 νŽ˜μ΄μ§€ 와 μœ μ‚¬ν•œ 였λ₯˜ 검사λ₯Ό μ‚¬μš©ν•˜λŠ” seccomp μ΄ˆκΈ°ν™” ​​루틴 μ „μ²΄μž…λ‹ˆλ‹€.

λ‹Ήμ‹ μ˜ ν•„ν„°λŠ” λ‚˜μ—κ²Œ ν•©λ¦¬μ μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

무엇이 잘λͺ»λ  수 μžˆλŠ”μ§€(λ˜λŠ” 무엇이 잘λͺ»λ˜κ³  μžˆλŠ”μ§€ μžμ„Ένžˆ μ•Œμ•„λ³΄λŠ” 방법), λ˜λŠ” 이것이 μ–΄λ–€ μ‹μœΌλ‘œλ“  μ˜ˆμƒλ˜λŠ” κ²½μš°μ— λŒ€ν•œ 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ? μ—­λ™μ μœΌλ‘œ μ›€μ§μ΄λŠ” 뢀뢄이 λ§Žμ§€ μ•ŠμœΌλ©° λ¬Έμ„œμ—μ„œ μ™œ 이런 일이 λ°œμƒν•  수 μžˆλŠ”μ§€μ— λŒ€ν•œ λ‚΄μš©μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.

v2.4.3 seccomp_load() μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ‹ˆ libseccompκ°€ -EINVAL 의 λ°˜ν™˜ μ½”λ“œλ₯Ό μƒμ„±ν•˜λŠ” 곳이 두 곳뿐인 것 κ°™μŠ΅λ‹ˆλ‹€.

μœ„μ˜ 두 였λ₯˜λŠ” λͺ¨λ‘ μœ νš¨ν•˜μ§€ μ•Šμ€ ν•„ν„°λ‘œ 인해 λ°œμƒν•©λ‹ˆλ‹€. λ‹Ήμ‹ μ˜ ν•„ν„° μ½”λ“œλ₯Ό 기반으둜 ν•  것 같지 μ•ŠμŠ΅λ‹ˆλ‹€.

seccomp_set_mode_filter() μžˆλŠ” μ»€λ„μ˜ κΈ°λ³Έ λ°˜ν™˜ κ°’ 은 -EINVAL μ΄λ―€λ‘œ μ‹œμŠ€ν…œμ˜ λ‹€λ₯Έ ν•­λͺ©μ΄ λ³€κ²½λ˜μ–΄ ν•΄λ‹Ή 경둜둜 λ–¨μ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. Dockerμ—μ„œ μ‹€ν–‰ 쀑이라고 μ–ΈκΈ‰ν–ˆμŠ΅λ‹ˆλ‹€. κΈ°λ³Έ Docker seccomp ν•„ν„°λ₯Ό λΉ„ν™œμ„±ν™”ν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

seccomp_load() μ‹€νŒ¨ ν›„ if λ‚΄λΆ€μ˜ μ½”λ“œμ— 디버깅을 더 μΆ”κ°€ν•˜κ³  싢을 κ²ƒμž…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ ν•„ν„° 자체의 PFC 및/λ˜λŠ” BPFλ₯Ό 좜λ ₯ν•˜μ—¬ ν•©λ¦¬μ μœΌλ‘œ λ³΄μ΄λŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. seccomp_export_pfc() 및 seccomp_export_bpf() .

v2.4.3 seccomp_load() μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ‹ˆ libseccompκ°€ -EINVAL 의 λ°˜ν™˜ μ½”λ“œλ₯Ό μƒμ„±ν•˜λŠ” 곳이 두 곳뿐인 것 κ°™μŠ΅λ‹ˆλ‹€.

gen_bpf_generate(...) λ˜λŠ” κ·Έ μ΄ν•˜μ—μ„œ 발견된 λͺ¨λ“  μ‹€νŒ¨λŠ” src/system.c:267 μ—μ„œ sys_filter_load(...) 에 μ˜ν•΄ -ENOMEM에 효과적으둜 κ²°ν•©λ©λ‹ˆλ‹€.

λ‚˜λŠ” "κΈ°μ–΅ 손상"으둜 λ˜λŒμ•„κ°€λŠ” 것을 μ‹«μ–΄ν•œλ‹€! λ„ˆλ¬΄ λΉ λ₯΄μ§€λ§Œ μ—¬κΈ°μ—μ„œλŠ” 그럴 수 μžˆμŠ΅λ‹ˆλ‹€.

λΉ λ₯΄κ³  μžμ„Έν•œ λ‹΅λ³€ κ°μ‚¬ν•©λ‹ˆλ‹€! 그듀은 μ—¬λŸ¬ 탐색 경둜λ₯Ό μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€.slightly_smiling_face:

μ—…κ·Έλ ˆμ΄λ“œ 이후 ν”„λ‘œκ·Έλž¨μ—μ„œ λ‹€λ₯Έ μ΄μƒν•œ λ™μž‘μ„ λ°œκ²¬ν•˜μ…¨μŠ΅λ‹ˆκΉŒ? λ‹€λ₯Έ 곳에 문제λ₯Ό μΌμœΌν‚€λŠ” λ©”λͺ¨λ¦¬ 손상 λ¬Έμ œκ°€ μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

μ•„λ‹ˆ, μ΄κ²ƒλ§Œ. 우리의 λ‹¨μœ„ 및 톡합 ν…ŒμŠ€νŠΈλŠ” 계속 ν†΅κ³Όν•˜κ³  있으며 이 맀우 λ“œλ¬Έ EINVAL ν•˜κ³ λŠ” prod에 였λ₯˜κ°€ κΈ°λ‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 ν™•μ‹€νžˆ 그것을 어리λ‘₯μ ˆν•˜κ²Œ λ§Œλ“­λ‹ˆλ‹€. λ‚˜λŠ” λ˜ν•œ λ©”λͺ¨λ¦¬ 손상을 μ˜μ‹¬ν–ˆμ§€λ§Œ 그것을 λ’·λ°›μΉ¨ν•  증거λ₯Ό 찾지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€ :slightly_frowning_face:

μ’€ 더 μžμ„Έν•œ λ‚΄μš©μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • ν”„λ‘œκ·Έλž¨μ€ Cython을 톡해 일뢀 C++λ₯Ό ν˜ΈμΆœν•˜λŠ” Python μ•±μž…λ‹ˆλ‹€(GIL은 이 μ‹œκ°„ λ™μ•ˆ μœ μ§€λ˜λ―€λ‘œ Python은 λ‹€λ₯Έ μŠ€λ ˆλ“œμ— ν• λ‹Ήν•˜μ§€ μ•ŠμŒ)
  • C++ μ‚¬μ΄λ“œ 포크 및 μžμ‹μ—μ„œ exec 전에 seccomp ν•„ν„°λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.
  • post-fork, pre-execμ—μ„œ λ°œμƒν•˜λŠ” λͺ¨λ“  λ©”λͺ¨λ¦¬ 할당은 seccomp_init λ“±μ—μ„œ libseccomp μžμ²΄μ—μ„œ λ°œμƒν•©λ‹ˆλ‹€.
  • C++ μ½”λ“œ 호좜과 λΆ„κΈ° 사이에 μ •ν™•νžˆ 4개의 λ°°μ—΄ malloc 이 있으며, λͺ¨λ‘ Cython에 있으며 μ“°κΈ° μ‹œ μ μ ˆν•œ λ²”μœ„κ°€ μžˆμŠ΅λ‹ˆλ‹€(라인 435λŠ” 이전에 μ—°κ²°λœ seccomp μ½”λ“œλ₯Ό ν˜ΈμΆœν•¨) -- λ‹€λ₯Έ λͺ¨λ“  ν• λ‹Ή/μ“°κΈ° λ“±. 파이썬 인터프리터 내에 μžˆμŠ΅λ‹ˆλ‹€

이것을 μž…λ ₯ν•˜λŠ” λ™μ•ˆ 아이디어가 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. malloc 포크 ν›„ μ‚¬μš©ν•˜κΈ°μ— μ•ˆμ „ν•˜μ§€ μ•Šλ‹€λŠ” λ¬΄μ„œμš΄ 이야기λ₯Ό λ“€μ—ˆκ³  libseccomp μžμ²΄μ— λͺ‡ 가지가 μžˆμŠ΅λ‹ˆλ‹€. Python μ•± μžμ²΄λŠ” _is_ 닀쀑 μŠ€λ ˆλ“œμ΄μ§€λ§Œ κΈ°λ³Έ μ½”λ“œμ— μžˆλŠ” λ™μ•ˆ 항상 GIL을 μœ μ§€ν•˜λ―€λ‘œ μ•ˆμ „ν•΄μ•Ό ν•©λ‹ˆλ‹€(?). ν•˜μ§€λ§Œ malloc-after-forkλ₯Ό 톡해 ꡐ착 μƒνƒœκ°€ λ°œμƒν•œλ‹€λŠ” μ΄μ•ΌκΈ°λ§Œ λ“€μ—ˆμŠ΅λ‹ˆλ‹€. (이것이 λ‹€μŒ λΉ„μ¦ˆλ‹ˆμŠ€ μˆœμ„œκ°€ seccomp_init 등을 포크 전에 μ΄λ™ν•˜κ³  seccomp_load 포슀트 포크만 ν˜ΈμΆœν•˜κ³  였λ₯˜κ°€ 계속 λ°œμƒν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.)

seccomp_load()κ°€ μ‹€νŒ¨ν•œ ν›„ if λ‚΄λΆ€μ˜ μ½”λ“œμ— 디버깅을 더 μΆ”κ°€ν•˜κ³  싢을 κ²ƒμž…λ‹ˆλ‹€.

μ œμ•ˆν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! seccomp_export_pfc 에 λŒ€ν•œ ν˜ΈμΆœμ„ μΆ”κ°€ν•˜κ³  μž…λ ₯ λ‚΄μš©μ„ ν•„ν„°( config->syscall_whitelist )에 λ€ν”„ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ— 이것이 μ‹€νŒ¨ν•˜λ©΄ 후속 쑰치λ₯Ό μ·¨ν•˜κ² μŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” @Xyene - μ•½ 일주일이

λΆˆν–‰νžˆλ„ 아직 μ•„λ‹™λ‹ˆλ‹€. seccomp_export_pfc 패치λ₯Ό μΆ”κ°€ν•œ ν›„ μΉ¨λ¬΅ν–ˆμŠ΅λ‹ˆλ‹€. μ–΄μ œ μ €λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμ„ λ•Œ 문제λ₯Ό μΊ‘μ²˜ν•˜κΈ° μœ„ν•΄ ν•΄λ‹Ή 패치λ₯Ό λͺ¨λ“  VM(단지 ν…ŒμŠ€νŠΈμš©μ΄ μ•„λ‹Œ)에 ν‘Έμ‹œν–ˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 침묡을 μ΄μƒν•˜κ²Œ μƒκ°ν•˜μ§€λ§Œ μ§€κΈˆμ€ λͺ¨λ“  디버깅/내보내기 논리가 seccomp_load μ‹€νŒ¨ _ν›„_ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— μš°μ—°μ˜ 일치둜 μƒκ°ν•˜κ³  μžˆμœΌλ―€λ‘œ μ‹€νŒ¨ μžμ²΄μ— 영ν–₯을 μ£Όμ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€.

진전!

그것이 μΉ¨λ¬΅ν–ˆλ˜ μ΄μœ λŠ” seccomp_export_bpf 이 segfaulting( seccomp_load λ‹€μŒμ— 호좜된 경우 ν•΄μ•Ό ν•©λ‹ˆκΉŒ?)이고, λ‚΄κ°€ seccomp μ‹€νŒ¨λ₯Ό μ°Ύκ³  있던 곳이 μ•„λ‹Œ λ‹€λ₯Έ κ³³μ—μ„œ λ³΄κ³ λ˜μ—ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 더 μ€‘μš”ν•œ 것은 ~150회 ν˜ΈμΆœμ—μ„œ 문제λ₯Ό μ•ˆμ •μ μœΌλ‘œ μž¬ν˜„ν•  수 μžˆλŠ” κ²½μš°μ— λΆ€λ”ͺμ³€κΈ° λ•Œλ¬Έμ— 일뢀 λ°°κ΄€ μž‘μ—…μ„ 톡해 일뢀 μ½”μ–΄ 덀프λ₯Ό μΆ”μΆœν•  수 μžˆμ–΄μ•Ό ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

μ’‹μ•„, λ‚˜λŠ” μ½”μ–΄ 덀프λ₯Ό κΊΌλƒˆκ³  이것이 μΆ”μ μ΄μ—ˆλ‹€: https://gist.github.com/Xyene/920f1cb098784a031f53c66a2f49d167

이것은 jemalloc의 realloc 루틴 λ‚΄μ—μ„œ μΆ©λŒν•˜κΈ° λ•Œλ¬Έμ— μ•½κ°„ μ˜μ‹¬μŠ€λŸ¬μ› μŠ΅λ‹ˆλ‹€. λ˜ν•œ glibc malloc을 λŒ€μ‹  μ‚¬μš©ν•˜λ©΄ λ¬Έμ œκ°€ ν•΄κ²°λ©λ‹ˆλ‹€(λΆˆν–‰νžˆλ„ 쑰각화 문제둜 인해 이 경우 μž₯κΈ° μ˜΅μ…˜μ΄ μ•„λ‹™λ‹ˆλ‹€).

λ‹€μŒμœΌλ‘œ jemalloc을 가져와 -O0 및 디버깅 기호둜 μ»΄νŒŒμΌν•˜κ³  μž¬μƒμ‚°μ„ λ‹€μ‹œ μ‹€ν–‰ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 이후가 μ•„λ‹ˆλΌ seccomp_load μ—μ„œ μΆ©λŒν–ˆμŠ΅λ‹ˆλ‹€! 여기에 κ·Έ 좔적을 μ—…λ‘œλ“œν–ˆμŠ΅λ‹ˆλ‹€: https://gist.github.com/Xyene/5da56168bcea337da85b2cd30704d12e

ν•΄λ‹Ή μΆ”μ μ˜ μŠ€λ‹ˆνŽ«:

#9  0x00007ff962698495 in free (ptr=0x5a5a5a5a5a5a5a5a) at src/jemalloc.c:2867
No locals.
#10 0x00007ff96062d087 in _program_free (prg=prg@entry=0x7ff95e963010) at gen_bpf.c:511
No locals.
#11 0x00007ff96062f605 in gen_bpf_release (program=program@entry=0x7ff95e963010) at gen_bpf.c:1986
No locals.
#12 0x00007ff96062c04f in sys_filter_load (col=col@entry=0x7ff95e9a5000) at system.c:293
        rc = -1
        prgm = 0x7ff95e963010
#13 0x00007ff96062b666 in seccomp_load (ctx=ctx@entry=0x7ff95e9a5000) at api.c:286
        col = 0x7ff95e9a5000

jemalloc을 κ²€μƒ‰ν•˜λ©΄ 0x5a κ°€ 이미 ν•΄μ œλœ 것을 ν•΄μ œν•˜λ €κ³  μ‹œλ„ν•˜λŠ” μ½”λ“œλ₯Ό μΆ©λŒμ‹œν‚€λŠ” νŠΉμ • μ˜λ„ 둜 μ—¬μœ  λ°”μ΄νŠΈλ₯Ό free둜 ν‘œμ‹œν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

v2.4.3의 gen_bpf.c:511 λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€. https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L505 -L513

κ·ΈλŸ¬λ‚˜ 이것은 ν”„λ‘œκ·Έλž¨μ˜ 수λͺ…이 sys_filter_load 의 본문일 λΏμ΄λ―€λ‘œ μ˜λ―Έκ°€ μ—†μŠ΅λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/system.c#L260 -L296

λ‚˜λŠ” 적어도 ν•˜λ‚˜μ˜ 문제λ₯Ό λ°œκ²¬ν–ˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. gen_bpf_generate ;

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L1963 -L1966

state.bpf = prgm zmalloc κ°€ μ‹€νŒ¨ν•˜μ§€ μ•ŠλŠ” ν•œ _gen_bpf_build_bpf κ°€ 호좜되고 rc λ₯Ό 기반으둜 state.bpf κ°€ NULL λ©λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L1968 -L1971

rc != 0 , state.bpf κ°€ _state_release 호좜 μ‹œ prgm 둜 μ„€μ •λ˜μ–΄ μžˆλŠ” 경우λ₯Ό κ³ λ €ν•˜λ©΄. 그러면 prgm κ°€ κ°€λ¦¬ν‚€λŠ” λ©”λͺ¨λ¦¬κ°€ ν•΄μ œλ©λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L539

λ‹€μŒμœΌλ‘œ gen_bpf_generate λŠ” ν•΄μ œλ˜μ—ˆμ§€λ§Œ μ—¬μ „νžˆ 0이 μ•„λ‹Œ 포인터인 return prgm μž…λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L1971 -L1974

sys_filter_load λŒμ•„κ°€λ©΄ gen_bpf_generate λ°˜ν™˜λ˜κ³  prgm λŠ” NULL μ•„λ‹ˆλ―€λ‘œ 계속 μ§„ν–‰ν•©λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/system.c#L265 -L267

λ§ˆμ§€λ§‰μœΌλ‘œ sys_filter_load 의 λμ—μ„œ gen_bpf_release κ°€ 이미 λΉ„μ–΄ μžˆλŠ” prgm 에 λŒ€ν•΄ ν˜ΈμΆœλ©λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/system.c#L292 -L295

이것은 _gen_bpf_build_bpf κ°€ μ²˜μŒμ— μ‹€νŒ¨ν•˜λŠ” μ΄μœ μ— λŒ€ν•œ 우렀λ₯Ό ν•΄κ²°ν•˜μ§€ μ•Šμ§€λ§Œ μ‹€νŒ¨ν•  경우 λ°œμƒν•  수 μžˆλŠ” λ‚˜μœ κ²ƒμ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€.

νŽΈμ§‘: μ‹€μ œλ‘œ 이것은 https://github.com/seccomp/libseccomp/commit/3a1d1c977065f204b96293cccfe7d3e5aa0d7ace 의 λΆ€μž‘μš©μœΌλ‘œ μˆ˜μ •λœ 것 κ°™μŠ΅λ‹ˆλ‹€

rc != 0인 경우λ₯Ό κ³ λ €ν•˜λ©΄ state.bpfλŠ” _state_release 호좜 μ‹œ μ—¬μ „νžˆ prgm으둜 μ„€μ •λ©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ prgm이 κ°€λ¦¬ν‚€λŠ” λ©”λͺ¨λ¦¬κ°€ ν•΄μ œλ©λ‹ˆλ‹€.

μ•„ν•˜! 쒋은 캐치 @Xyene!

3a1d1c977065f204b96293cccce7d3e5aa0d7ace μ΄μƒμœΌλ‘œ 이 문제λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μž μ‹œ 생각해 λ³΄κ² μŠ΅λ‹ˆλ‹€... μˆ˜μ •μ΄ λ„ˆλ¬΄ μ–΄λ €μšΈ 것이라고 μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€... 그리고 PR을 ν•  수 μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.

3a1d1c9 μ΄μƒμœΌλ‘œ 이 문제λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μž μ‹œ 생각을 해보죠... μˆ˜μ •μ΄ λ„ˆλ¬΄ μ–΄λ €μšΈ 것 κ°™μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€... 그리고 PR을 ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€.

이런, λ‚˜λŠ” 그것을 μž‘μ„±ν•  λ•Œ 였래된 μ½”λ“œλ₯Ό 보고 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 예, 3a1d1c9κ°€ 이 문제λ₯Ό ν•΄κ²°ν•œλ‹€κ³  μƒκ°ν•˜μ§€λ§Œ 릴리슀 2.4 뢄기에 λŒ€ν•œ νŒ¨μΉ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€. 이제 μž‘μ—…ν•˜κ² μŠ΅λ‹ˆλ‹€.

_(메타: 계속 μ§„ν–‰ν•˜λ©΄μ„œ 이 λ©”μ‹œμ§€λ₯Ό λ‚΄ 발견으둜 계속 μ—…λ°μ΄νŠΈν•  μ˜ˆμ •μ΄λ―€λ‘œ 슀팸 메일을 보내지 μ•Šκ³  기둝할 수 μžˆλŠ” 곳이 μžˆμŠ΅λ‹ˆλ‹€. :)_

μ’‹μ•„, νŒ¨μΉ˜κ°€ 적용된 2.4.3으둜 λŒμ•„κ°€μ„œ μ‹€νŒ¨ν•œ ν•„ν„°λ₯Ό κΊΌλ‚Ό 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€: link .

보고 된 원인은 μ§€κΈˆ ENOMEM λŒ€μ‹  EINVAL λ‚΄κ°€ μƒκ°ν•˜λŠ”μ΄, 주어진 μ˜ˆμƒλœλ‹€ _gen_bpf_build_bpf μ‹€νŒ¨ν•˜κ³  λ°˜ν™˜ NULL ν”„λ‘œκ·Έλž¨μ„. κ·ΈλŸ¬λ‚˜ PFCλŠ” 잘 μΈμ‡„λ©λ‹ˆλ‹€. _gen_bpf_build_bpf 의 λ°˜ν™˜ 값을 λ³΄κ³ ν•˜λ„λ‘ seccomp μ½”λ“œλ₯Ό μˆ˜μ •ν•˜λ©΄ EFAULT κ°€ μ›μΈμœΌλ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€.

λΉ λ₯Έ ν•΄ν‚ΉμœΌλ‘œ :%s/return -EFAULT/abort() over src/gen_bpf.c λ₯Ό μ‹€ν–‰ν•˜κ³  이 μŠ€νƒ 좔적을 μΆ”μΆœν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

EFAULT μŠ€νƒ 좔적

(gdb) bt full
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
        set = {__val = {0, 140084028365964, 140083248439464, 140083248438968, 140083248431088, 140084028368143, 28659884033, 140083965300736, 
            140083248439464, 140083248438968, 140083248431088, 140084028351031, 140084019988760, 140083248439624, 140083248431200, 140084028372597}}
        pid = <optimized out>
        tid = <optimized out>
        ret = <optimized out>
#1  0x00007f67daa4d55b in __GI_abort () at abort.c:79
        save_stage = 1
        act = {__sigaction_handler = {sa_handler = 0x7f67d6f3eec0, sa_sigaction = 0x7f67d6f3eec0}, sa_mask = {__val = {140083965300736, 
              140083965300736, 0, 0, 140083248438968, 140083248438968, 140083248439464, 140083248431504, 140084028417173, 140083964793344, 
              140083965300736, 140083248431552, 140083994791895, 140083248431552, 140083994787642, 140083965300736}}, sa_flags = -1404894496, 
          sa_restorer = 0x0}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007f67d8bfd455 in _gen_bpf_build_bpf (state=0x7f67ac4302e0, col=0x7f67d6f63040) at gen_bpf.c:1943
        rc = 0
        iter = 1
        h_val = 1425818561
        res_cnt = 0
        jmp_len = 0
        arch_x86_64 = 0
        arch_x32 = -1
        instr = {op = 32, jt = {tgt = {imm_j = 0 '\000', imm_k = 0, hash = 0, db = 0x0, blk = 0x0, nxt = 0}, type = TGT_NONE}, jf = {tgt = {
              imm_j = 0 '\000', imm_k = 0, hash = 0, db = 0x0, blk = 0x0, nxt = 0}, type = TGT_NONE}, k = {tgt = {imm_j = 4 '\004', imm_k = 4, 
              hash = 4, db = 0x4, blk = 0x4, nxt = 4}, type = TGT_K}}
        i_iter = 0x7f67d6fdcb60
        b_badarch = 0x7f67d6fd9000
        b_default = 0x7f67d6fd9060
        b_head = 0x7f67d6fda1a0
        b_tail = 0x7f67d6fd9000
        b_iter = 0x0
        b_new = 0x7f67d6fe3300
        b_jmp = 0x0
        db_secondary = 0x0
        pseudo_arch = {token = 0, token_bpf = 0, size = ARCH_SIZE_UNSPEC, endian = ARCH_ENDIAN_LITTLE, syscall_resolve_name = 0x0, 
          syscall_resolve_num = 0x0, syscall_rewrite = 0x0, rule_add = 0x0}
#3  0x00007f67d8bfd560 in gen_bpf_generate (col=0x7f67d6f63040) at gen_bpf.c:1971
        rc = 0
        state = {htbl = {0x0 <repeats 256 times>}, attr = 0x7f67d6f63044, bad_arch_hsh = 889798935, def_hsh = 742199527, arch = 0x7f67ac4301e0, 
          bpf = 0x7f67d6f64010}
        prgm = 0x7f67d6f64010
#4  0x00007f67d8bf64a7 in sys_filter_load (col=0x7f67d6f63040) at system.c:265
        rc = 32615
        prgm = 0x0
#5  0x00007f67d8bf4f10 in seccomp_load (ctx=0x7f67d6f63040) at api.c:287
        col = 0x7f67d6f63040

μ΄λŠ” 1943행에 ν•΄λ‹Ήν•©λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/1dde9d94e0848e12da20602ca38032b91d521427/src/gen_bpf.c#L1935 -L1943

λŒ€μ²΄μ˜ νŠΉμ„±μ„ κ°μ•ˆν•  λ•Œ λ„μš°λ―Έ ν•¨μˆ˜μ—μ„œ EFAULT λ₯Ό μ œμ™Έν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ 그것듀이 λ¨Όμ € μ€‘λ‹¨λ˜μ—ˆμ„ 것이기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

κ·Έ ν›„, λ‚˜λŠ” HEAD둜 λ™μΌν•œ 것을 μž¬ν˜„ν•˜λ €κ³  μ‹œλ„ν–ˆμŠ΅λ‹ˆλ‹€. μ—¬μ „νžˆ λ°œμƒν•©λ‹ˆλ‹€. λ‹€μŒμœΌλ‘œ %s:/goto build_bpf_free_blks/abort() λ₯Ό λ°˜λ³΅ν•©λ‹ˆλ‹€. 원인은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

https://github.com/seccomp/libseccomp/blob/34bf78abc9567b66c72dbe67e7f243072162a25f/src/gen_bpf.c#L2219 -L2220

κ³ λ§™κ²Œλ„ 이 κΈ°λŠ₯은 짧고 μ†Œμˆ˜μ˜ μ‹€νŒ¨ μ§€μ λ§Œ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. λ‚˜μ€‘μ— abort λΌμš΄λ“œ;

μΆ”μ ν•˜λ‹€

(gdb) bt full
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
        set = {__val = {0, 140050183343588, 0, 448, 140049402494880, 140049402509040, 140049402494832, 140050183342988, 140049402495088, 
            140049402509040, 140049402494896, 140050183343588, 4294967296, 140049402509040, 140049402509040, 140049402509040}}
        pid = <optimized out>
        tid = <optimized out>
        ret = <optimized out>
#1  0x00007f5ff953055b in __GI_abort () at abort.c:79
        save_stage = 1
        act = {__sigaction_handler = {sa_handler = 0x7f5ff595d260, sa_sigaction = 0x7f5ff595d260}, sa_mask = {__val = {139642271694862, 
              140050119389792, 0, 0, 140049402502840, 0, 140049402503336, 140049402502888, 140049402502840, 112, 384, 140049402502840, 140050149861504, 
              140049402495328, 140050149857273, 392}}, sa_flags = 448, sa_restorer = 0x7f5ff595d240}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007f5ff76edee5 in _bpf_append_blk (prg=0x7f5ff5964010, blk=0x7f5ff59df1a0) at gen_bpf.c:452
        rc = -12
        i_new = 0x0
        i_iter = 0x7f5ff59fa178
        old_cnt = 48
        iter = 1
#3  0x00007f5ff76f3716 in _gen_bpf_build_bpf (state=0x7f5fcae302d0, col=0x7f5ff59c5000) at gen_bpf.c:2223
        rc = 0
        iter = 1
        h_val = 1425818561
        res_cnt = 0
        jmp_len = 0
        arch_x86_64 = 0
        arch_x32 = -1
        instr = {op = 32, jt = {tgt = {imm_j = 0 '\000', imm_k = 0, hash = 0, db = 0x0, blk = 0x0, nxt = 0}, type = TGT_NONE}, jf = {tgt = {
              imm_j = 0 '\000', imm_k = 0, hash = 0, db = 0x0, blk = 0x0, nxt = 0}, type = TGT_NONE}, k = {tgt = {imm_j = 4 '\004', imm_k = 4, 
              hash = 4, db = 0x4, blk = 0x4, nxt = 4}, type = TGT_K}}
        i_iter = 0x7f5ff59e1b60
        b_badarch = 0x7f5ff59de000
        b_default = 0x7f5ff59de060
        b_head = 0x7f5ff59df1a0
        b_tail = 0x7f5ff59de000
        b_iter = 0x7f5ff59df1a0
        b_new = 0x7f5ff59e8300
        b_jmp = 0x7f5ff59df0e0
        db_secondary = 0x0
        pseudo_arch = {token = 0, token_bpf = 0, size = ARCH_SIZE_UNSPEC, endian = ARCH_ENDIAN_LITTLE, syscall_resolve_name = 0x0, 
          syscall_resolve_num = 0x0, syscall_rewrite = 0x0, rule_add = 0x0}
#4  0x00007f5ff76f3874 in gen_bpf_generate (col=0x7f5ff59c5000, prgm_ptr=0x7f5fcae30b40) at gen_bpf.c:2270
        rc = 0
        state = {htbl = {0x0, 0x7f5ff593ef80, 0x7f5ff593efe0, 0x7f5ff593efc0, 0x0, 0x7f5ff595d000, 0x7f5ff593ef60, 0x7f5ff593ef00, 
            0x0 <repeats 248 times>}, attr = 0x7f5ff59c5004, bad_arch_hsh = 889798935, def_hsh = 742199527, bpf = 0x7f5ff5964010, 
          arch = 0x7f5fcae301c0, b_head = 0x7f5ff59e8300, b_tail = 0x7f5ff59de120, b_new = 0x7f5ff59e8300}
        prgm = <optimized out>
#5  0x00007f5ff76eb275 in sys_filter_load (col=0x7f5ff59c5000, rawrc=false) at system.c:307
        rc = 0
        prgm = 0x0
#6  0x00007f5ff76e9505 in seccomp_load (ctx=0x7f5ff59c5000) at api.c:386
        col = 0x7f5ff59c5000
        rawrc = false

https://github.com/seccomp/libseccomp/blob/34bf78abc9567b66c72dbe67e7f243072162a25f/src/gen_bpf.c#L449 -L452

λ”°λΌμ„œ realloc λ‹€μ‹œ μ‹€νŒ¨ν•˜κ³  _bpf_append_blk λŠ” _gen_bpf_build_bpf μ˜ν•΄ λ§ˆμŠ€ν‚Ήλ˜μ–΄ -EFAULT -ENOMEM λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 이것은 큰 λ¬Έμ œλŠ” μ•„λ‹ˆμ§€λ§Œ 더 λ‚˜μ€ 였λ₯˜ 보고가 2.5의 λͺ©ν‘œλΌκ³  λ§ν–ˆκΈ° λ•Œλ¬Έμ— 이것이 λ²”μœ„ λ‚΄μ—μ„œ 보이기 λ•Œλ¬Έμ— μ–ΈκΈ‰ν•  것이라고 μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€ :slightly_smiling_face:

일뢀 GDBλ₯Ό νŒŒκ³ λ“€κΈ°:

(gdb) f 2
#2  0x00007f5ff76edee5 in _bpf_append_blk (prg=0x7f5ff5964010, blk=0x7f5ff59df1a0) at gen_bpf.c:452
452         abort();
(gdb) info args
prg = 0x7f5ff5964010
blk = 0x7f5ff59df1a0
(gdb) print prg->blks
$4 = (bpf_instr_raw *) 0x7f5ff59fa000
(gdb) x/32bx &prg->blks
0x7f5ff5964018: 0x00    0xa0    0x9f    0xf5    0x5f    0x7f    0x00    0x00
0x7f5ff5964020: 0x5a    0x5a    0x5a    0x5a    0x5a    0x5a    0x5a    0x5a
0x7f5ff5964028: 0x5a    0x5a    0x5a    0x5a    0x5a    0x5a    0x5a    0x5a
0x7f5ff5964030: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
(gdb) print ((prg)->blk_cnt * sizeof(*((prg)->blks)))
$5 = 392
(gdb) print prg->blk_cnt
$6 = 49

이것은 μ •λ§λ‘œ ν• λ‹Ήμž μ‹€νŒ¨μ²˜λŸΌ 보이기 μ‹œμž‘ν•©λ‹ˆλ‹€...

μ•„ν•˜, 이 μ΄μ•ΌκΈ°λŠ” λ§ˆμΉ¨λ‚΄ _슀릴링_ν•œ_ 결둠에 λ„λ‹¬ν–ˆμŠ΅λ‹ˆλ‹€. 무슨 일이 μΌμ–΄λ‚˜κ³  μžˆλŠ”μ§€ μ•Œμ•„λƒˆκ³  μˆ˜μ • 사항을 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.slightly_smiling_face:

ν₯미둜운 이야기가 될 수 μžˆμœΌλ―€λ‘œ 여기에 μžˆμŠ΅λ‹ˆλ‹€.

μž‘μ—…μžλ₯Ό λΆ„κΈ°ν•˜λŠ” μ£Όμš” ν”„λ‘œμ„ΈμŠ€λŠ” 일반적으둜 ~80mb RSS에 μžˆμŠ΅λ‹ˆλ‹€. λΆ„κΈ° ν›„μ—λŠ” rlimit λ₯Ό 톡해 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ μ œν•œν•˜λ©° λ•Œλ‘œλŠ” 64MB둜 μ œν•œν•©λ‹ˆλ‹€. 이것은 ν˜„μž¬ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ ν•œκ³„λ₯Ό μ΄ˆκ³Όν•˜λŠ” μœ„μΉ˜μ— λ†“μ΄κ²Œ λ˜μ§€λ§Œ 이것은 rlimit ν—ˆμš©λ©λ‹ˆλ‹€. _λŒ€λΆ€λΆ„μ˜_ λ©”λͺ¨λ¦¬ ν• λ‹ΉμžλŠ” 컀널에 μΆ”κ°€ μš”μ²­ 없이 libseccomp의 μ΄ˆκΈ°ν™” 루틴을 μ²˜λ¦¬ν•˜κΈ°μ— μΆ©λΆ„ν•œ μ—¬μœ  λ©”λͺ¨λ¦¬λ₯Ό κ°–κ²Œ λ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 그것이 _ν•˜μ§€ μ•ŠλŠ”_ 경우, 그리고 μΆ”κ°€ κ²½κΈ°μž₯μ΄λ‚˜ 무언가λ₯Ό μœ„ν•œ 곡간을 μš”μ²­ν•  ν•„μš”κ°€ μžˆμ„ λ•Œ, ν”„λ‘œμ„ΈμŠ€κ°€ 이미 ν•œκ³„λ₯Ό μ΄ˆκ³Όν–ˆκΈ° λ•Œλ¬Έμ— 컀널은 그것을 μ œκ³΅ν•˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

2.4.3μ—μ„œ 이 λ©”λͺ¨λ¦¬ νšλ“ μ‹€νŒ¨λŠ” EINVAL 및 이쀑 자유둜 λ‚˜νƒ€λ‚©λ‹ˆλ‹€. λ§ˆμŠ€ν„° 포슀트 https://github.com/seccomp/libseccomp/commit/3a1d1c977065f204b96293cccfe7d3e5aa0d7ace μ—μ„œ EFAULT λŒ€μ‹  λ³΄κ³ λ©λ‹ˆλ‹€. https://github.com/seccomp/libseccomp/pull/257을 μ μš©ν•˜λ©΄ ENOMEM κ°€ μ˜¬λ°”λ₯΄κ²Œ λ³΄κ³ λ©λ‹ˆλ‹€.

이것이 맀우 λ“œλ¬Όκ²Œ μΌμ–΄λ‚˜λŠ” μ΄μœ λŠ” λͺ…λ°±ν•΄μ§‘λ‹ˆλ‹€. ν• λ‹Ήμžκ°€ 컀널에 더 λ§Žμ€ 것을 μš”μ²­ν•˜μ§€ μ•Šκ³  BPF ν”„λ‘œκ·Έλž¨μ„ λΉŒλ“œν•˜κΈ°μ— μΆ©λΆ„ν•œ λ©”λͺ¨λ¦¬κ°€ μžˆλŠ”μ§€ 여뢀에 μ „μ μœΌλ‘œ μ˜μ‘΄ν•©λ‹ˆλ‹€. glibc의 ν• λ‹ΉμžλŠ” 쑰각화가 μŒ“μ΄λ„λ‘ ν—ˆμš©ν•˜λŠ” 것에 λŒ€ν•΄ 더 λŠμŠ¨ν•˜κΈ° λ•Œλ¬Έμ— μ œμžλ¦¬μ— μžˆλŠ” κ²½μš°μ—λŠ” 이런 일이 λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. jemalloc은 더 μ—„κ²©ν•œ 경계λ₯Ό μ„€μ •ν•˜κ³  seccomp_load λ™μ•ˆ λ©”λͺ¨λ¦¬λ₯Ό μš”μ²­ν•΄μ•Ό ν•  ν™•λ₯ μ„ λ†’μž…λ‹ˆλ‹€.

μˆ˜μ •μ€ λͺ¨λ“  setrlimit ν˜ΈμΆœμ„ _after_ seccomp_load μž…λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ realloc κ°€ 더 이상 _bpf_append_blk μ—μ„œ μ‹€νŒ¨ν•˜μ§€ μ•Šκ³  ν•„ν„°κ°€ μ„±κ³΅μ μœΌλ‘œ λ‘œλ“œλ©λ‹ˆλ‹€. 이것은 ν•„ν„°κ°€ setrlimit ν—ˆμš©ν•΄μ•Ό 함을 μ˜λ―Έν•˜μ§€λ§Œ 제 κ²½μš°μ—λŠ” 이것이 ν—ˆμš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 보닀 일반적으둜 이 λ¬Έμ œλŠ” https://github.com/seccomp/libseccomp/issues/123 κ³Ό 같은 λ°©λ²•μœΌλ‘œ 해결될 것이라고 μƒκ°ν•©λ‹ˆλ‹€

@pcmoore , @drakenclimber -- 이 문제λ₯Ό λ””λ²„κΉ…ν•˜λŠ” 데 도움을 μ£Όμ…”μ„œ λ‹€μ‹œ ν•œ 번 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€! μ§€κΈˆ 제 뒀에 놓을 수 μžˆμ–΄μ„œ κΈ°μ©λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ·€ν•˜μ˜ ν¬μΈν„°λŠ” 거기에 λ„λ‹¬ν•˜λŠ” 데 맀우 μ€‘μš”ν–ˆμŠ΅λ‹ˆλ‹€.슀마일리:

이 λ²„κ·ΈλŠ” https://github.com/seccomp/libseccomp/commit/c0a6e6fd15f74c429a0b74e0dfd4de5a29aabebd μ»€λ°‹μœΌλ‘œ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰