Kernel Live Patching: Vá lỗ hổng Linux mà không cần ác mộng khởi động lại

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Cái giá đắt của thông báo ‘Yêu cầu khởi động lại’

Bây giờ là 3 giờ chiều thứ Sáu. Một lỗ hổng CVE nghiêm trọng vừa xuất hiện—thứ gì đó đáng sợ như ‘Dirty Pipe’ (CVE-2022-0847). Trưởng nhóm bảo mật yêu cầu vá lỗi ngay. Trên máy tính cá nhân, sudo reboot chỉ là một chút phiềnóái. Nhưng trên một database sản xuất xử lý 5.000 truy vấn mỗi giây, việc khởi động lại là một cơn ác mộng. Bạn đối mặt với việc rớt kết nối. Bạn đối mặt với downtime. Tệ nhất là, bạn phải dành cả tiếng đồng hồ căng thẳng để kiểm tra xem mọi dịch vụ đã hoạt động bình thường trở lại hay chưa.

Chúng ta từng chấp nhận rằng cập nhật kernel đồng nghĩa với việc phải khởi động lại. Kernel là trái tim của hệ điều hành; bạn không thể thay tim khi đang chạy marathon được. Hay là có thể? Kernel Live Patching đã thay đổi cuộc chơi. Nó cho phép chúng ta chuyển hướng mã nguồn bị lỗi sang phiên bản an toàn trong thời gian thực. Bộ đếm thời gian uptime vẫn chạy, và máy chủ của bạn vẫn an toàn.

Cơ chế hoạt động: Phép màu diễn ra như thế nào?

Thay đổi kernel khi nó đang chạy nghe giống như việc sửa động cơ máy bay ngay giữa tầng không. Trong Linux, chúng ta thực hiện việc này bằng ftrace. Hãy coi nó như một hệ thống điều hướng động cho mã nguồn của bạn.

Đường vòng ftrace

Hầu hết các giải pháp hiện đại, bao gồm kpatchkgraft, đều sử dụng hạ tầng ftrace của kernel. Khi bạn áp dụng một bản vá (patch), hệ thống sẽ để lại đoạn mã cũ bị lỗi trong bộ nhớ. Nó không xóa bất cứ thứ gì. Thay vào đó, nó đặt một ‘hook’ ngay tại điểm bắt đầu của hàm bị lỗi. Khi CPU cố gắng thực thi mã đó, ftrace sẽ chặn cuộc gọi. Nó lập tức chuyển hướng thực thi sang một hàm mới đã được vá nằm ở vị trí khác trong RAM.

Quá trình chuyển đổi này là nguyên tử (atomic). Kernel sẽ chờ đợi một khoảnh khắc ‘an toàn’ khi không có tiến trình nào đang bị kẹt giữa đoạn mã đang thay đổi. Điều này giúp ngăn chặn tình trạng crash. Một khi hook được kích hoạt, đoạn mã cũ sẽ nằm im, và hệ thống của bạn sẽ chạy logic bảo mật mới một cách hiệu quả.

Chọn đúng công cụ cho hạ tầng của bạn

Việc chọn công cụ thường phụ thuộc vào bản phân phối (distro) bạn đang dùng. Mặc dù logic ‘chuyển hướng’ bên dưới là tương tự nhau, nhưng các lớp quản lý sẽ khác nhau giữa các nhà cung cấp:

  • Canonical Livepatch: Tiêu chuẩn cho Ubuntu. Nó là một phần của bộ Ubuntu Pro.
  • kpatch: Sản phẩm của Red Hat. Đây là mặc định cho RHEL, AlmaLinux và Rocky Linux.
  • Ksplice: Một trong những cái tên tiên phong, hiện thuộc sở hữu của Oracle. Đây là tính năng cốt lõi của Oracle Linux.
  • kgraft: Bản triển khai được tìm thấy trong SUSE Linux Enterprise Server (SLES).

Thực hành: Kích hoạt Canonical Livepatch trên Ubuntu

Vì hầu hết các workload đám mây chạy trên Ubuntu, hãy cùng xem quy trình tôi thường dùng. Canonical cung cấp gói miễn phí cho tối đa năm máy. Điều này hoàn hảo cho các dự án cá nhân hoặc hệ thống nhỏ.

1. Chuẩn bị Snap Daemon

Client Livepatch chạy dưới dạng một snap. Nếu bạn đang dùng bản cloud ‘minimal’ rút gọn, hãy đảm bảo snapd đã sẵn sàng:

sudo apt update
sudo apt install snapd

2. Kết nối máy chủ

Livepatch đi kèm with Ubuntu Pro client. Lấy mã token từ bảng điều khiển Ubuntu Pro và kết nối thực thể (instance) của bạn:

sudo pro attach [TOKEN_CỦA_BẠN_TẠI_ĐÂY]

3. Kích hoạt

Việc bật dịch vụ chỉ tốn đúng một câu lệnh:

sudo pro enable livepatch

Client sẽ lập tức quét phiên bản kernel của bạn và tải xuống bất kỳ bản vá bảo mật nào hiện có.

Liệu việc này có làm giảm hiệu năng?

Tôi thường nghe các quản trị viên lo lắng rằng các hook ftrace sẽ làm CPU bị quá tải. Theo kinh nghiệm của tôi trên một web server Ubuntu 22.04 với 4GB RAM, chi phí tài nguyên (overhead) chưa đến 0,1%. Lợi ích mang lại là cực lớn. Bạn giữ cho các cache hệ thống tập tin luôn ‘nóng’. Bạn tránh được độ trễ ‘khởi động lạnh’ (cold start) khi ứng dụng bị chậm trong mười phút sau khi khởi động lại. Với 99% các workload, sự sụt giảm hiệu năng là không đáng kể. Nếu bạn đang chạy các giao dịch tần suất cao với độ trễ cực thấp, hãy benchmark trước. Còn không, đừng quá bận tâm.

Xác minh lá chắn

Đừng bao giờ tin tưởng tuyệt đối; hãy luôn kiểm chứng. Bạn có thể kiểm tra xem bản vá nào đang hoạt động bằng lệnh kiểm tra trạng thái nhanh:

canonical-livepatch status

Hãy tìm dòng patchState: applied trong kết quả trả về. Điều này xác nhận rằng kernel của bạn đã được bảo vệ trước các lỗ hổng đã biết mà phần cứng không bao giờ bị ngắt điện.

Giới hạn của Live Patching

Live patching là một con dao mổ, không phải là một chiếc búa tạ. Nó dành cho các **bản vá bảo mật**, không phải để cập nhật tính năng. Nếu bạn muốn nhảy từ kernel 5.15 lên 6.8 để có hỗ trợ Wi-Fi tốt hơn hoặc tính năng Btrfs mới, bạn vẫn cần khởi động lại.

Ngoài ra, một số bản vá quá phức tạp. Nếu một lỗi yêu cầu thay đổi các cấu trúc dữ liệu cơ bản trên toàn bộ kernel, nhà cung cấp có thể đánh dấu nó là ‘yêu cầu khởi động lại’. Live patching giúp bạn kéo dài thời gian, nhưng nó không thay thế hoàn toàn việc bảo trì định kỳ.

Quy tắc của tôi để vận hành ổn định

Sau khi quản lý hàng trăm node, tôi tuân theo ba quy tắc sau:

  1. Không cập nhật tất cả cùng lúc: Hãy triển khai so le. Vá lỗi môi trường staging vào thứ Ba, môi trường sản xuất vào thứ Tư. Nếu một bản vá tương tác kém với ứng dụng cụ thể của bạn, bạn sẽ muốn phát hiện ra nó ở môi trường staging.
  2. Theo dõi logs: Chạy lệnh dmesg -w sau khi vá lỗi. Tìm kiếm các lỗi ‘kernel oops’ hoặc các vết stack trace bất thường.
  3. Lên lịch khởi động lại định kỳ: Tôi vẫn khởi động lại 90 ngày một lần. Việc này giúp dọn dẹp bộ nhớ bị phân mảnh và đảm bảo cuối cùng chúng ta cũng chuyển sang bản build kernel gốc mới nhất.

Live patching biến bảo mật từ một cuộc khủng hoảng gây gián đoạn thành một tác vụ chạy ngầm lặng lẽ. Đây là cách tốt nhất để giữ cho máy chủ của bạn an toàn trong khi vẫn tận hưởng trọn vẹn những ngày cuối tuần.

Share: