Kiến thức nền
Vụ sập 'Lo': Báo cáo lỗi đầu tiên của internet
Tại sao máy tính của SRI sập sau khi Charley Kline gõ ba chữ cái, điều gì thực sự hỏng, và cách một buffer overflow trong một tính năng tự hoàn thành trở thành câu chuyện nguồn gốc của internet.
TL;DR
Ngày 29 tháng 10 năm 1969, một nghiên cứu sinh UCLA tên Charley Kline gõ ba chữ cái qua liên kết ARPANET đầu tiên hoạt động — L, O, G — và máy ở đầu bên kia sập. Nguyên nhân không phải là mạng. Đó là một tính năng tự hoàn thành thông minh ở phía SRI cố gắng gửi lại nhiều byte hơn buffer xuất của nó có thể chứa. Việc sửa mất khoảng một giờ. Toàn bộ LOGIN đã thành công tối hôm đó. Không ai nhớ sự thành công. Mọi người nhớ “Lo”.
Bối cảnh
Đó là buổi tối ngày 29 tháng 10 năm 1969. Hai Interface Message Processor đã được cài đặt — một ở UCLA đầu tháng 9, một ở SRI ở Menlo Park đầu tháng 10. Liên kết liên lục địa giữa chúng đã hoạt động được khoảng ba tuần. Chưa ai thực sự sử dụng nó.
Tại UCLA, Charley Kline 21 tuổi, một lập trình viên tại Network Measurement Center của Leonard Kleinrock. Anh ngồi tại một teletype kết nối với một mainframe SIGMA 7. Cách đó ba trăm năm mươi dặm về phía bắc, tại Augmentation Research Center của SRI, Bill Duvall ngồi tại một SDS 940 chạy hệ thống chia sẻ thời gian Genie.
Mục tiêu khiêm tốn: đăng nhập từ xa. Kline sẽ gõ lệnh trên terminal của UCLA, các ký tự sẽ đi qua hai IMP đến SRI, SRI sẽ xử lý chúng, và các phản hồi sẽ quay lại. Một phiên tương tác bình thường — chỉ khác là bàn phím và máy tính ở các bang khác nhau.
Hai lập trình viên phối hợp qua điện thoại.
Ba phím bấm
Lời nhắc đăng nhập của SRI yêu cầu bạn gõ LOGIN. Bill Duvall đã viết phần mềm host, và anh đã thêm một tính năng nhỏ để cải thiện trải nghiệm: tự hoàn thành lệnh. Nếu bạn gõ bất kỳ tiền tố duy nhất nào của một lệnh, hệ thống sẽ điền phần còn lại cho bạn. Gõ LO đủ để xác định LOGIN một cách rõ ràng, nên SRI sẽ trả về các ký tự còn lại.
Kline gõ L. SRI trả về L.
Kline gõ O. SRI trả về O.
Kline gõ G. SRI sập.
Qua điện thoại, Duvall nói hệ thống đã ngưng hoạt động. Kline nhìn terminal của mình. Ký tự cuối cùng nó nhận được là một phần của tự hoàn thành mà SRI đã bắt đầu gửi — rồi không có gì.
Thông điệp đầu tiên từng được gửi qua ARPANET là đoạn hai ký tự Lo.
Điều gì thực sự hỏng
Tự hoàn thành lệnh nghe vô hại. Lỗi nằm ở cách SRI đệm các phản hồi đi ra.
Khi Kline gõ G, SRI nhận ra LOG là một tiền tố của LOGIN và xếp các ký tự còn lại — I, N, cộng với phần đuôi thường thấy của prompt — vào một buffer gửi để phản hồi. Buffer được định kích cỡ cho một ký tự phản hồi, vì đó là trường hợp bình thường: echo một phím mỗi lần. Đột ngột được yêu cầu giữ một chuỗi hoàn thành nhiều ký tự, nó tràn. Trên một SDS 940 chạy OS nghiên cứu vào năm 1969, một tràn không được kiểm tra trong một buffer hệ thống đủ để hạ máy.
Không có bảo vệ bộ nhớ theo nghĩa hiện đại. Không có sự tách biệt giữa buffer của routine echo và phần còn lại của workspace hệ điều hành. Hệ thống không sập vì mạng không đáng tin cậy — các byte đến chính xác như đã gửi. Nó sập vì một tính năng cục bộ có một lỗi cục bộ, được phơi bày lần đầu bởi lưu lượng đến từ ngoài máy.
UCLA SIGMA 7 SRI SDS 940
│ │
│────── L ────────────────────>│
│<───── L ──────────────────────│ echo
│ │
│────── O ────────────────────>│
│<───── O ──────────────────────│ echo
│ │
│────── G ────────────────────>│
│ │ → kích hoạt tự hoàn thành
│ │ → buffer xếp "IN<CR><LF>..."
│ │ → tràn → hệ thống dừng
│ 💥 │
Kline đã gửi hai ký tự tải trọng và kích hoạt thứ mà, theo thuật ngữ hiện đại, chúng ta sẽ gọi là denial-of-service từ xa do buffer overflow trong đường echo. Hoàn toàn tình cờ.
Một giờ sau
Duvall xây lại hệ thống. Chi tiết của bản vá đã mất trong lịch sử thông thường — có thể anh đã tăng buffer, hoặc vô hiệu hóa tự hoàn thành cho terminal từ xa, hoặc cả hai. Khoảng 22:30, họ thử lại.
Kline gõ L, O, G, I, N. Cả năm ký tự đều được trả về. SDS 940 nhắc tên người dùng. Kline gõ một cái. Hệ thống đăng nhập anh vào.
Lần đăng nhập từ xa thành công hoàn toàn đầu tiên trong lịch sử xảy ra tối hôm đó. Nó không tạo ra ảnh chụp màn hình, không có bài báo, và không có huyền thoại. Cái được viết xuống — trong nhật ký phòng lab của Kleinrock, trong một dòng khô khan — là thứ đã hỏng một giờ trước đó.
22:30 Talked to SRI Host to Host
Không đề cập đến Lo. Không đề cập đến vụ sập. Phải mất nhiều năm trước khi câu chuyện được tái dựng từ trí nhớ và được đặt vào khuôn khổ nổi tiếng như bây giờ.
Tại sao điều này trở thành câu chuyện nguồn gốc
Kỹ sư yêu thích các câu chuyện nguồn gốc là những thất bại. Một vụ sập có thể chia sẻ được. Một lần đăng nhập thành công thì không. Câu chuyện “Lo” chứa đựng, ở dạng thu nhỏ, mọi thứ mà năm mươi năm kỹ thuật internet tiếp theo sẽ phải vất vả đúc kết:
- Bug là tính năng dưới tải. Tự hoàn thành hoạt động cho mọi người dùng cục bộ từng sử dụng nó. Nó thất bại lần đầu tiên khi chạy với một người gọi từ xa, vì các giả định về thời gian và kích thước tải trọng không đúng qua mạng.
- Mạng là phần ít tin cậy nhất, cho đến khi nó không phải. Các IMP làm công việc của mình hoàn hảo. Vụ sập nằm bên trong một host, trong code có trước mạng.
- Mọi giao thức thất bại đầu tiên ở các trường hợp biên. Một byte dư duy nhất vượt qua ranh giới buffer. Mô hình đó —
fingerdcủa Morris Worm, Heartbleed, mọi CVE với “improper bounds checking” trong tiêu đề — là cùng một chế độ thất bại, cách nhau năm mươi năm và chín số 0 quy mô triển khai. - Bạn không thể kiểm tra một mạng cho đến khi bạn sử dụng nó. ARPANET đã “hoạt động” trong nhiều tuần. Không ai biết nó hỏng cho đến khi họ chạy lưu lượng thật.
Bài viết ARPANET coi Lo như một giai thoại thú vị. Nó cũng là mục đầu tiên trong một bug tracker hiện có vài tỷ vé mở. Lần đăng nhập đã thành công một giờ sau. Mô hình nó tiết lộ vẫn đang hoạt động hôm nay.