Hiểu các lệnh gọi hệ thống Linux với lệnh lạc chỗ
Khi các chương trình chạy trên Linux muốn sử dụng các tài nguyên do hệ điều hành quản lý (đọc tệp, tạo quy trình, v.v.), chúng sẽ thực hiện lệnh gọi hệ thống tới HĐH. Các lệnh gọi hệ thống hoạt động ở cấp độ hạt nhân và thực hiện các hoạt động cần thiết, để lại quyền kiểm soát cho chương trình gọi. Công cụ strace cung cấp khả năng theo dõi các lệnh gọi hệ thống này trên Linux.
Mục Lục
Sử dụng điển hình của Lệnh đi lạc
Để giám sát các lệnh gọi của hệ thống cho một ứng dụng, chỉ cần gọi lệnh với đi lạc ở định dạng sau:
strace ls /tmp
Tuy nhiên, thường có các quy trình bắt đầu sớm hơn nhiều và tiếp tục hoạt động ở chế độ nền. Do bất kỳ vấn đề nào, bạn có thể muốn thu thập thêm thông tin liên quan đến các quy trình đó. Bạn có thể đính kèm đi lạc cho bất kỳ ứng dụng nào đang chạy bằng cách cung cấp ID quy trình của quy trình cho -P tham số:
strace -p 2759
Đầu ra:
Theo dõi các chuỗi và ngã ba của một ứng dụng
Với strace, bạn có thể kiểm tra tất cả các chuỗi và các quy trình con khác là một nhánh của ứng dụng bằng cách sử dụng -f lá cờ.
strace -f -p 2759
Đầu ra:
Kiểm tra các cuộc gọi hệ thống nhất định có lạc chỗ
Đôi khi, kết quả đầu ra mặc định có thể khá đông đúc. Nếu bạn chỉ muốn theo dõi các cuộc gọi hệ thống nhất định, bạn có thể làm như vậy với -e tham số:
strace -f -e trace=open,write,close,connect,select -p 19770
Để chỉ theo dõi các lệnh gọi hệ thống liên quan đến hoạt động tệp, hãy sử dụng -e trace = tập tin:
strace -e trace=file -p 19770
Để chỉ lọc các cuộc gọi hệ thống liên quan đến mạng, hãy chỉ định -e trace = mạng trong lệnh:
strace -e trace=network -p 19770
Nhận thông tin thời gian trong vài giây
Khi xuất các lệnh gọi hệ thống, bạn có thể sử dụng -t tham số để nhận thông tin thời gian với độ chính xác tính bằng giây. Hầu hết thời gian độ chính xác sẽ không đủ cho nhu cầu của bạn. Trong những tình huống như vậy, bạn có thể sử dụng -tt tham số để nhận thông tin thời gian với độ chính xác micro giây:
strace -tt ls /tmp
Thu thập số liệu thống kê về cuộc gọi hệ thống
Với -c bạn có thể thu thập số liệu thống kê về lệnh gọi hệ thống miễn là bạn muốn:
strace -f -c -p 19770
Lưu nhật ký vào tệp
Nếu bạn chạy lạc trong một thời gian dài và muốn kiểm tra các bản ghi kết quả chi tiết hơn sau đó, bạn sẽ cần phải lưu các bản ghi. Với -o tham số bạn có thể chỉ định tệp mà strace sẽ lưu nhật ký:
strace -f -o /tmp/strace.log -e trace=file ls /tmp
Quy trình chặn ptrace
Sử dụng lệnh gọi hệ thống prctl, bất kỳ ứng dụng nào trong Linux đều có thể ngăn chính nó khỏi bị người dùng không phải root điều khiển bằng ptrace. Nếu ứng dụng xóa PR_SET_DUMPABLE tự gắn cờ thông qua prctl, người dùng không phải root sẽ không thể kiểm soát ứng dụng này bằng ptrace, ngay cả khi họ có quyền báo hiệu ứng dụng.
Một trong những cách sử dụng điển hình nhất của tính năng này được thấy trong phần mềm tác nhân xác thực OpenSSH. Do đó, việc kiểm soát ứng dụng bởi một ứng dụng khác với ptrace bị ngăn chặn khi xác thực người dùng.
ptrace và bảo mật
Do cơ sở ptrace được đặt trong mô hình quy trình Linux truyền thống, bất kỳ phần mềm nào bạn chạy trên hệ thống với người dùng của mình đều có quyền chèn mã độc hại vào đó. Từ công cụ xterm đơn giản nhất đến các ứng dụng trình duyệt web nâng cao, phần mềm độc hại như vậy có thể kiểm soát tất cả các ứng dụng đang chạy khác của bạn — nhờ lệnh gọi hệ thống ptrace — và sao chép thông tin quan trọng mà bạn không nhận ra.
Để đối phó với tình trạng này mà nhiều người dùng không biết, một cơ chế bảo vệ đã được phát triển với mô-đun bảo mật có tên là Yama trong nhân Linux.
Bạn có thể kiểm soát phản hồi đối với lệnh gọi hệ thống ptrace thông qua / proc / sys / kernel / yama / ptrace_scope tập tin. Theo mặc định, tệp này ghi giá trị bằng 0.
Các giá trị sau có thể chấp nhận được:
| Giá trị | Nghĩa |
| 0 | Hành vi thông thường: Tất cả các ứng dụng có quyền ptrace có thể được kiểm tra. |
| 1 | Ptrace bị hạn chế: Chỉ cha mẹ trực tiếp của ứng dụng hoặc gỡ lỗi các ứng dụng được ứng dụng cho phép với PR_SET_PTRACER tùy chọn có quyền kiểm soát. Do đó, việc sử dụng gdb program_name và tên_chương_trình đi lạc sẽ tiếp tục hoạt động, nhưng bạn sẽ không thể đính kèm ứng dụng đang chạy sau đó. |
| 2 | Chuyển cho quản trị viên hệ thống: Chỉ các ứng dụng được xác định CAP_SYS_PTRACE thuộc tính hoặc quy trình con xác định PTRACE_TRACEME tùy chọn với prctl có thể được kiểm soát. |
| 3 | Hoàn toàn bị vô hiệu hóa: Không ptrace được phép trong bất kỳ trường hợp nào. Nếu thuộc tính này được xác định một lần, bạn không thể thay đổi lại nó trong thời gian chạy. |
Nhiều nhà phát triển không biết rằng các ứng dụng có thể tự vô hiệu hóa ptrace thông qua prctl, ngoại trừ người dùng root. Mặc dù phần mềm liên quan đến bảo mật như tác nhân OpenSSH thực hiện các hoạt động này, nhưng sẽ không đúng khi mong đợi hành vi giống nhau từ tất cả phần mềm đang chạy trên hệ thống.
Gần đây, một số bản phân phối Linux đã bắt đầu đặt giá trị mặc định của ptrace_scope tệp, được mô tả ở trên, 1. Do đó, với các hoạt động ptrace bị hạn chế, một môi trường làm việc an toàn hơn sẽ được cung cấp trên toàn hệ thống.
Sử dụng một đoạn ví dụ
Đăng ký đơn mẫu bên dưới với tên Ministrace.c. Sau đó, bạn có thể biên dịch nó bằng lệnh sau:
gcc -o ministrace ministrace.c
Mã số:
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int wait_for_syscall (pid_t child)
{
int status;
while (1) {
ptrace(PTRACE_SYSCALL, child, 0, 0);
waitpid(child, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80)
return 0;
if (WIFEXITED(status))
return 1;
}
}int do_child (int argc, char **argv)
{
char *args [argc+1];
memcpy(args, argv, argc * sizeof(char*));
args[argc] = NULL;
ptrace(PTRACE_TRACEME);
kill(getpid(), SIGSTOP);
return execvp(args[0], args);
}
int do_trace (pid_t child)
{
int status, syscall, retval;
waitpid(child, &status, 0);
ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD);
while(1) {
if (wait_for_syscall(child) != 0) break;
syscall = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*ORIG_RAX);
fprintf(stderr, "syscall(%d) = ", syscall);
if (wait_for_syscall(child) != 0) break;
retval = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RAX);
fprintf(stderr, "%d
", retval);
}
return 0;
}
int main (int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s prog args
", argv[0]);
exit(1);
}
pid_t child = fork();
if (child == 0) {
return do_child(argc-1, argv+1);
} else {
return do_trace(child);
}
}
Sau khi biên dịch ứng dụng, bạn có thể chạy bất kỳ lệnh nào với bộ trưởng và kiểm tra đầu ra:
Bạn có thể sử dụng dây mảnh cho nhiều mục đích
strace có thể giúp tìm ra lỗi trong các chương trình sử dụng tài nguyên hệ thống một cách không cần thiết. Tương tự như vậy, đặc điểm mà một chương trình thể hiện trong khi sử dụng tài nguyên hệ điều hành cũng có thể bị lộ ra ngoài.
Vì strace trực tiếp lắng nghe các lệnh gọi của hệ thống, nó có thể tiết lộ động lực thời gian chạy bất kể mã của chương trình đang chạy là mở / đóng. Có thể có một ý tưởng về lý do tại sao các chương trình gặp lỗi khi bắt đầu sử dụng strace.
Tương tự, strace giúp bạn hiểu lý do tại sao một chương trình kết thúc bất ngờ. Do đó, việc làm quen với strace là rất quan trọng trong việc phát triển nhân Linux và quản trị hệ thống.
Đọc tiếp