fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987) - #3

Open
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit
Open

fix(hpux): net_io_counters()가 미초기화 힙을 NIC 이름으로 반환하던 문제 (SERVER-1987)#3
Y-JaeHyun wants to merge 1 commit into
mainfrom
fix/SERVER-1987-hpux-netio-uninit

Conversation

@Y-JaeHyun

Copy link
Copy Markdown
Collaborator

배경/목적

HP-UX(IA) 장비에서 에이전트 작업 디렉토리에 이름이 깨진 0바이트 파일이 계속 쌓였습니다(whaHP_IA 실측: / 1140개, /test 1327개). 추적 결과 원인은 이 확장의 psutil_net_io_counters()미초기화 힙 메모리를 인터페이스 이름으로 반환하는 것이었습니다.

ID_ifNumber(논리 인터페이스 수)만큼 루프를 도는데, get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있습니다.

  • 실측: ifNumber = 4, 실제로 채워지는 것은 lan0 / lan1 / lo03개
  • 버퍼를 malloc으로 잡아 초기화하지 않아 4번째 항목은 이전 힙 내용이 남아 있고, nm_device[0]=='\0' 가드도 통과

40회 호출 40회 모두 재현됩니다:

'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'

바이트를 뜯어보면 무작위가 아니라 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열입니다.

이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어, >가 섞이면 파일이 생기고 다른 메타문자면 root 권한 명령 실행으로 이어질 수 있었습니다. 에이전트 쪽 차단은 별도 PR(B안)로 진행합니다.

변경 내용

  • malloccalloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가 의도대로 동작합니다. get_physical_stat의 정확한 계약과 무관하게 안전한 수정입니다.
  • get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로 루프를 제한합니다. 아니면 no-op이라 손해가 없습니다.
  • count <= 0이면 빈 dict 반환 — 기존에는 count 초기값 -1malloc(음수*size) 경로가 있었습니다.
  • 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장합니다.

테스트

대상 장비(whaHP_IA, HP-UX B.11.23 IA)에서 실제 헤더로 컴파일 검증:

cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> -I. _psutil_hpux.c
→ 에러 0, 경고 0 (_psutil_hpux.o 생성)

⚠️런타임 검증은 아직입니다. 번들 cc로 임시 링크한 .so는 Python 심볼 해석 문제로 로드에 실패해, 정식 빌드(setup.py) 산출물로 확인이 필요합니다. 리뷰어께서 정식 빌드로 net_io_counters() 키에 쓰레기가 사라지는지 확인해 주시면 좋겠습니다.

파리티 영향

없음 (HP-UX 전용 경로).

문서

없음.

관련

  • SERVER-1987
  • 에이전트 측 차단(B안): whatap/python-infra fix/SERVER-1987-hpux-nic-shell-injection

🤖 Generated with Claude Code

psutil_net_io_counters()는 ID_ifNumber(논리 인터페이스 수)만큼 루프를 돌지만,
get_physical_stat()이 실제로 채우는 항목 수는 그보다 적을 수 있다.
whaHP_IA(HP-UX 11.23 IA) 실측: ifNumber=4 인데 채워지는 것은 lan0/lan1/lo0 3개.
버퍼를 malloc으로 잡아 초기화하지 않았기 때문에 4번째 항목은 이전 힙 내용이
그대로 남아 있었고, nm_device[0]=='\0' 가드도 통과해 미초기화 메모리가
인터페이스 이름으로 반환됐다. 실측 40회 호출 40회 모두 재현:
'lo0', 'lan1', 'lan0', '~\xe6\xbb\x80~\xe6\xbb\xa0~\xe6\xbb\xc0~\xe6\xbb\xe0~\xe6\xbc'
바이트를 뜯어보면 32바이트 간격의 빅엔디안 32비트 힙 포인터 배열이다.
이 이름은 python-infra 에이전트에서 'ifconfig ' + name 형태로 셸에 전달되어,
'>' 가 섞이면 작업 디렉토리에 파일을 만들고 다른 메타문자면 root 권한 명령
실행으로 이어질 수 있었다(SERVER-1987 B안에서 별도 차단).
- malloc -> calloc: 채워지지 않은 항목이 0으로 남아 기존 nm_device 가드가
의도대로 동작한다. get_physical_stat 의 정확한 계약과 무관하게 안전하다.
- get_physical_stat 반환값이 항목 수로 보이면(0 <= ret < count) 그 값으로
루프를 제한한다. 아니면 no-op 이므로 손해가 없다.
- count <= 0 이면 빈 dict 반환. 기존에는 count 초기값 -1 로 malloc(음수*size)
경로가 있었다.
- 이름이 필드를 가득 채운 경우를 대비해 사용 직전 널 종료를 보장한다.
검증: 대상 장비(whaHP_IA)에서 실제 헤더로 컴파일 확인
cc -c +z -DPSUTIL_VERSION=596 -I<python2.7 include> _psutil_hpux.c -> 에러 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Y-JaeHyun