1. Sử dụng lệnh strace
Để 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 strace như 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. Bạn có thể muốn thu thập thông tin bổ sung liên quan đến các quy trình đó. Bạn có thể đính kèm strace vào bất kỳ ứng dụng nào đang chạy bằng cách cung cấp ID tiến trình (process ID) của tiến trình cho tham số -p:
strace -p 2759
Đầu ra:
1.1 Theo dõi các luồng (thread) và nhánh (fork) của một ứng dụng
Với strace, bạn có thể kiểm tra tất cả các luồng (thread) 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 cờ -f.
strace -f -p 2759
Đầu ra:
1.2 Kiểm tra một số cuộc gọi hệ thống với strace
Đôi khi, kết quả đầu ra mặc định có thể khá khó theo dõi. Nếu bạn chỉ muốn theo dõi các lệnh gọi hệ thống nhất định, bạn có thể làm như vậy với tham số -e:
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=file:
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=network trong lệnh:
strace -e trace=network -p 19770
1.3 Nhận thông tin thời gian tính bằng giây
Khi xuất lệnh gọi hệ thống, bạn có thể sử dụng tham số -t để nhận thông tin thời gian với độ chính xác tính bằng giây. Trong hầu hết các trường hợp, độ 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 tham số -tt để nhận thông tin thời gian với độ chính xác micro giây:
strace -tt ls /tmp
1.4 Thu thập số liệu thống kê về cuộc gọi hệ thống
Với tham số -c, bạn có thể thu thập số liệu thống kê về các lệnh gọi hệ thống miễn là bạn muốn:
strace -f -c -p 19770
1.5 Lưu nhật ký vào tệp
Nếu bạn chạy strace 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 tham số -o, 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
2. 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 bản thân 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 cờ PR_SET_DUMPABLE cho chính nó 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.
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 một ứng dụng này kiểm soát một ứng dụng khác với ptrace bị ngăn chặn tại 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 — nhờ lệnh gọi hệ thống ptrace — và sao chép thông tin quan trọng mà bạn không hề hay biết.
Để đối phó với tình trạng này, 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 tệp /proc/sys/kernel/yama/ptrace_scope. Theo mặc định, tệp này ghi giá trị bằng 0.
Các giá trị sau được chấp nhận:
Giá trị | Ý nghĩa |
0 | Hành vi thông thường: Tất cả các ứng dụng có quyền ptrace đều có thể được kiểm tra. |
1 | Ptrace bị hạn chế: Chỉ ứng dụng mẹ (parent) trực tiếp của ứng dụng hoặc ứng dụng gỡ lỗi (debug app) được ứng dụng có tùy chọn PR_SET_PTRACER cho phép mới có quyền kiểm soát. Do đó, việc sử dụng gdb program_name và strace program_name 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 | Ptrace cho người quản trị hệ thống : Chỉ các ứng dụng có thuộc tính CAP_SYS_PTRACE đã xác định hoặc các quy trình con xác định tùy chọn PTRACE_TRACEME với prctl mới có thể được kiểm soát. |
3 | Hoàn toàn bị vô hiệu hóa: Không cho phép ptrace 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 bạn không nên 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 tệp ptrace_scope, được mô tả ở trên, thành 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.
3. Sử dụng một đoạn ví dụ
Đăng ký ứng dụng mẫu dưới đây với tên domainsrace.c. Sau đó, bạn có thể biên dịch nó bằng lệnh sau:
gcc -o ministrace ministrace.c
Code:
#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 Ministrace và kiểm tra đầu ra:
4. Bạn có thể sử dụng strace 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ị tiết lộ với 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.
>>> Nếu bạn đang có nhu cầu học lập trình trực tuyến, tìm hiểu ngay tại đây:
- Tất cả những điều bạn cần biết về khóa học lập trình tại FUNiX FPT
- 5 Điểm đáng chú ý tại khóa học lập trình trực tuyến FPT – FUNiX
- Từ A-Z chương trình học FUNiX – Mô hình đào tạo lập trình trực tuyến số 1 Việt Nam
- Lý do phổ biến khiến học viên nước ngoài chọn FUNiX
- Lưu ý để học blockchain trực tuyến hiệu quả cao tại FUNiX
- Lý do nữ giới nên chọn FUNiX để học chuyển nghề IT
- FUNiX trở thành đối tác của Liên minh Blockchain Việt Nam
- 3 lý do bạn trẻ nên học blockchain trực tuyến ở FUNiX
Vân Nguyễn
Dịch từ: https://www.makeuseof.com/strace-command-linux/
Bình luận (0
)