BSDCon에서 논문으로 발표되기도 했던 Colin Percival의 FreeBSD Update(security/freebsd-update)를 대충 살펴보았습니다. 우선, FreeBSD Update가 무엇이냐 하면, FreeBSD는 바이너리 기반으로 업데이트되는 시스템이 아니라서, 보안 패치가 나올 때마다 업데이트 하려면 cvsup으로 전체 소스 업데이트한 다음에 make world하고, 커널 패치면 make kernel한 뒤에 reboot까지 해야하는데, 보통 빠른 컴퓨터라도 이 과정이 30분 이상 걸리고, 뻑날 가능성도 많고 필요한 툴도 많은 건 그동안 다들 경험하셨을 겁니당. 엔터만 치면 다운로드 받아서 바로 업데이트되는 데비안에 비하면 정말 일반 사용자 입장에서는 고통입니다~ 한시라도 빨리 업데이트해야하는 상황에서.. 흐흐;;
그래서, FreeBSD Update에서는 바이너리로 쓱 업데이트해불는 데, 베이스 전체에 대한 바이너리 패치를 만들어서, 바이너리 패치를 다운받아서 업데이트를 하게 됩니다. 바이너리 패치는 misc/bsdiff 를 이용해서 만드는데, 이게 성능이 꽤 좋아서 diff 양이 엄청 적습니다. 흐흐. FreeBSD 4.7 릴리즈(2002년 9월)부터 지금까지 보안 패치를 패치가 아닌 그냥 변경된 파일 전체를 받으려면 36메가가 넘는데, bsdiff로 만들어진 패치는 621kB밖에 안 된다는군요. (만세!) 그리고, 기본 환경 설정의 핑거프린트를 씨앗으로 해서 웹 서버에서 공개키를 받아와서, 패치를 다운 받은 뒤에 그 패치의 무결성 검사도 하기 때문에, 믿고 자동 업데이트할 정도로 된답니다. 그런데, 지금은 아직 공식 사이트에서는 4.7과 4.8만 제공하고 있어서, 5.0이나 5.1에서는 쓸 수 없습니다. (저는 5.x 머신만 열라 많아서 테스트를 못 해봤;;) 참 그리고, 바이너리를 기반으로 패치하는 것이다보니 반드시 릴리즈 깔고 손을 안 대야합니다. 체크섬이 안 맞는 파일들은 전체를 새로 받아오니.. 업데이트가 제 구실을 못하는..
Colin Percival의 BSDCon 논문을 살펴보면, 단순히 생각해도 불가능하게만 보이는 바이너리 패치 업데이트를 어떻게 만들었는지 구구절절 써 놓았는데 정말 눈물납니다. 흐.. (아직 Debian이나 Redhat도 패치 기반이 아니라 전체 패키지를 받아와서 업데이트하는 방법이니, 패치기반 업데이트는 오픈소스에서는 거의 최초가 아닐까 싶네요.) 논문의 내용에 보면 대표적인 문제점들을 다음과 같이 해결하고 있습니다.
-
날짜가 바이너리 안에 들어가서, 빌드할 때마다 달라지는 바이너리: 커널, 부트로더, 펄 같이 빌드할 때 현재 시간을 넣어버리는 바이너리들은 빌드할 때마다 자동으로 바뀌기 때문에, 패치를 빌드할 때 패치 안 해도 되는게 쓸데없이 들어가게 되는데. 요 녀석들을 퇴치하기 위해서 일단, RELEASE를 한번 빌드하고 또 다른데서 한번 빌드해서, 같은 버전으로 빌드했는데도 달라진 파일을 뽑아서 블랙리스트에 올리고 나중에 그 파일들이 보안 업데이트가 필요한 경우에는 수동으로 넣는 방법으로 해결했다는 군요. 이런 파일은 FreeBSD 4.7의 보안 브랜치에서 모두 160개라고 합니다.
-
빌드 중에 랜덤 요소를 쓰는 파일: fortune이나 ntp같은 것들은 엔트로피를 좀 더 주려는 목적으로 빌드하다가 랜덤넘버를 컴파일된 파일에 넣어버립니다. (fortune은 데이터파일) 이런 것들을 랜덤을 안 쓰도록 모두 패치해버렸다고 합니다. (-ㅇ-)
-
전역 심볼이 없는 경우에 쓰레기 값이 들어가 버리는 바이너리: libobjc같이 이런 경우는 동적 라이브러리 에서 많이 발생하는데, gcc를 패치해서 이런 경우 빌드 디렉토리를 기준으로 일정한 값을 넣도록 패치했다고 합니다.
-
날짜 문자열이 길어져서 주소가 연달아 바뀌는 경우: 예를 들어 “February”가 “March”로 빌드하다가 바뀐 경우, 그 뒤에 있는 문자열들이 연달아서 주소가 밀려나서, 패치해야할 양이 엄청 늘어납니다. 이런 경우를 또 막기 위해서 가급적이면 0x00으로 최대 길이를 채우거나 하는 방법으로 패치해버렸다고 합니다.
그런데, 커널의 경우에는 SMP지원이나 HTT지원 때문에, 일반적인 환경에서도 자주 빌드해서 쓰기 때문에 이런 걸 쉽게 패치할 수 있게 하기 위해서, GENERIC에 SMP기능만 넣은 GENERIC-MP 커널을 제공하자고 제안하고 있군요. 하여간.. 그 엄청난 빌드 구조를 다 파악해서 패치를 했다니.. 입이 벌어질 따름입니다. 만세! 곧 5.1에서도 쓸 수 있게 되길 기대합니당~
어떤 옵션 주고 빌드해야 뎀?
LookupError: unknown encoding: X-MAC-KOREAN
에러나고 빌드 중지됨
http://sota.nonun.com/moniwiki/wiki.php/python/3_0_build_error
2.6은 되고, 3.0은 솥아옹이랑 같은 오류예요. 10.5.2
오오.. 다들 재현이 잘 되시는군요. 2.6은 문제가 없고 3.0에만 문제가 있는건가보네요 -ㅇ-; 그렇다면 3.0용 패치를 만드는 대로 올려볼게용 -ㅇ-;;
python + django 에서도 저런 오류 났는데 해결 되는 건가요 +_+
한날, try 안에 있는데 왜 에러가 나죠? 그냥 ascii로 지정될 거 같은데.
한날: 옙. 2.6과 3.0에 mackorean 코덱을 넣으려고 작업 중입니다. ^^;
# kz님/ 저기서는 에러가 안납니다. DEFAULT_ENCODING 에 X-MAC 어쩌고가 들어가는데, 이후 DEFAULT_ENCODING 변수를 쓰는 부분에서 X-MAC 어쩌고라는 코덱이 없다고 오류가 나지요.
아하! 😀