2010-06-09 28 views
51

OS X thiếu số strace của linux, nhưng có dtrace được cho là tốt hơn nhiều.Làm cách nào để có được lệnh dtrace để chạy lệnh theo dõi với các thuộc tính không phải root?

Tuy nhiên, tôi nhớ khả năng thực hiện truy tìm đơn giản trên các lệnh riêng lẻ. Ví dụ, trên linux Tôi có thể viết strace -f gcc hello.c để caputre tất cả các cuộc gọi hệ thống, mà mang lại cho tôi danh sách các tất cả các tên tập tin cần thiết bởi trình biên dịch để biên dịch chương trình của tôi (các memoize kịch bản tuyệt vời được xây dựng dựa trên thủ thuật này)

tôi muốn cổng ghi nhớ trên mac, vì vậy tôi cần một số loại strace. Những gì tôi thực sự cần là danh sách các tập tin gcc đọc và viết vào, vì vậy những gì tôi cần là nhiều hơn một truss. Chắc chắn tôi có thể nói dtruss -f gcc hello.c và nhận được phần nào chức năng tương tự, nhưng sau đó trình biên dịch được chạy với quyền sở hữu gốc, rõ ràng là không mong muốn (ngoài rủi ro bảo mật lớn, một vấn đề là tệp a.out hiện thuộc sở hữu của root :-)

sau đó tôi đã cố gắng dtruss -f sudo -u myusername gcc hello.c, nhưng điều này cảm thấy một chút sai lầm, và không hoạt động nào (tôi không nhận được a.out tập tin ở mọi thời đại này, không chắc chắn lý do tại sao)

Tất cả những gì câu chuyện dài cố gắng để thúc đẩy câu hỏi ban đầu của tôi : làm cách nào để nhận được dtrace để chạy lệnh của tôi với các đặc quyền người dùng thông thường, giống như strace có trong linux?

Edit: được dường như tôi không phải là người duy nhất tự hỏi làm thế nào để làm điều này: Câu hỏi #1204256 là khá nhiều giống như tôi (và có câu trả lời sudo tối ưu cùng :-)

Trả lời

5

Không phải là câu trả lời cho câu hỏi của bạn mà là điều cần biết. OpenSolaris giải quyết vấn đề này (một phần) với "đặc quyền" - xem this page. Ngay cả trong OpenSolaris, nó sẽ không thể cho phép một người dùng, mà không có bất kỳ đặc quyền bổ sung, để dtruss quá trình riêng của họ. Lý do là cách dtrace hoạt động - nó cho phép đầu dò trong hạt nhân. Vì vậy, cho phép người dùng không có đặc quyền thăm dò hạt nhân nghĩa là người dùng có thể thực hiện rất nhiều thứ không mong muốn, ví dụ: sniffing passwd của người dùng khác bằng cách cho phép đầu dò trong trình điều khiển bàn phím!

+0

Có lẽ bạn đang đúng. mặc dù có được đặc quyền root không phải là vấn đề ở đây, vì trên máy tính xách tay của tôi tôi có thể (và đã làm như vậy) 'chmod a + s dtrace', dtrace không được dùng như một công cụ" unix power user ", mà là" unix quản trị "công cụ. Đó là lý do tại sao cố gắng sử dụng nó từ các chương trình người dùng dẫn đến một tình huống như vậy. Cảm ơn rất nhiều cho câu trả lời của bạn. – Gyom

+0

Không thể có "chế độ hạn chế", chỉ một số đầu dò (như đầu dò syscall hoặc đầu dò vùng người dùng) sẽ kích hoạt và chỉ trong một số quy trình (những người thuộc sở hữu của người dùng có liên quan) và chỉ có một số chức năng : những người có thể dễ dàng được thực hiện để chỉ kiểm tra quy trình của riêng người dùng hoặc chỉ cung cấp quyền truy cập vào thông tin đã có sẵn cho người dùng theo các cách khác? – SamB

1

I don' t biết một cách để chạy những gì bạn muốn như một người dùng bình thường, vì nó có vẻ là dtruss, trong đó sử dụng dtrace đòi hỏi đặc quyền su.

Tuy nhiên, tôi tin rằng các lệnh bạn đang tìm kiếm thay vì

dtruss -f sudo -u myusername gcc hello.c

sudo dtruss -f gcc hello.c

Sau khi gõ vào mật khẩu của bạn, dtruss sẽ chạy đặc quyền sudo dtrace ý chí, và bạn sẽ nhận được dấu vết cũng như tệp a.out.

Rất tiếc, tôi không thể trợ giúp thêm.

+3

vấn đề với việc thực sự chạy lệnh như gốc (ngoài rủi ro bảo mật khổng lồ rõ ràng) là môi trường thời gian chạy của sudo (PATH, biến env, quyền) rất khác so với bình thường và tác động đáng kể đến hành vi của chương trình truy tìm. Linux 'strace', ngược lại, gần như là minh bạch về hành vi chức năng của lệnh truy tìm. – Gyom

5

Tôi không biết nếu bạn có thể nhận được dtruss được như không xâm lấn như strace.

Một biến thể của "sudo [để nhổ tận gốc] dtruss sudo [trở lại nonroot] cmd" mà dường như làm việc tốt hơn trong một số thử nghiệm nhanh đối với tôi là:

sudo dtruss -f su -l `whoami` cd `pwd` && cmd.... 

Các sudo bên ngoài là tất nhiên vì thế dtruss chạy như root.

Su trong trở lại với tôi, và với -l nó tái tạo môi trường đúng cách, tại thời điểm đó chúng ta cần phải cd trở lại nơi chúng ta bắt đầu.

Tôi nghĩ "su -l user" tốt hơn "sudo -u user" nếu bạn muốn môi trường là những gì người dùng thường nhận được.Đó sẽ là môi trường đăng nhập của họ mặc dù; Tôi không biết nếu có một cách tốt để cho môi trường kế thừa thông qua hai thay đổi người dùng thay thế.

Trong câu hỏi của bạn, một khiếu nại bổ sung mà bạn có về giải pháp "sudo dtruss sudo", khác với sự xấu xa, là "Tôi không nhận được tệp a.out vào thời điểm này, không chắc chắn lý do". Tôi không biết tại sao một trong hai, nhưng trong kịch bản thử nghiệm nhỏ của tôi, một "sudo dtruss sudo" biến thể cũng không ghi vào một tập tin đầu ra thử nghiệm, và "sudo dtruss su" biến thể ở trên đã tạo ra các tập tin đầu ra.

+0

thực sự, cảm ơn vì nỗ lực này. vẫn có vẻ như tôi sẽ phải từ bỏ cái này.Trên Linux, tôi đã sử dụng lệnh 'strace' từ một kịch bản lệnh thay thế makefile, để theo dõi những tập tin nào đã bị các lệnh này chạm vào. Tôi muốn chuyển các kịch bản này sang mac os x, nhưng vào cuối ngày tôi nhận ra rằng tôi không thích ý tưởng có tất cả các bản dựng của tôi liên quan đến một số cấp sudo chỉ để theo dõi các lệnh của riêng tôi. – Gyom

+0

Vâng. Trực tiếp cố gắng để làm cho hành động dtruss như một thay thế strace không xâm lấn có vẻ như sủa lên cây sai vì những lý do bạn mô tả. Có lẽ một cách tiếp cận thay thế là cần thiết. 2 điều xảy ra với tôi có thể xảy ra: 1) lấy nguồn dtrace, sửa đổi giao diện người dùng (cần chạy dưới dạng root) để nó chỉ khởi động các tiến trình mới và chỉ gián điệp trên đó, thêm tùy chọn để báo cho ai biết bắt đầu các quá trình đó, sau đó biến nó thành setuid thuộc sở hữu của root. – metamatt

+0

Và # 2 (tiếp tục từ bình luận trước): sử dụng dtrace trực tiếp cách nó được thiết kế để trả lời câu hỏi bạn muốn trả lời, thay vì cố gắng sử dụng nó như là một thay thế dropin cho strace trong makefiles của bạn để xem những gì các lệnh con đang làm - bạn có thể viết các đầu dò dtrace bên ngoài quá trình thực hiện để xác định và chú thích quá trình thực hiện đang làm gì không? – metamatt

39

Cách đơn giản nhất là sử dụng sudo:

sudo dtruss -f sudo -u $USER whoami 

giải pháp khác sẽ được chạy trình gỡ lỗi đầu tiên và theo dõi cho các quy trình cụ thể mới. Ví dụ:

sudo dtruss -fn whoami 

Sau đó, trong một ga chỉ cần chạy:

whoami 

đơn giản như vậy.

luận More khéo léo bạn có thể tìm thấy trong cuốn hướng dẫn: man dtruss


Hoặc bạn có thể đính kèm dtruss đến quá trình sử dụng chạy ví dụ trên Mac:

sudo dtruss -fp PID 

hoặc tương tự trên Linux/Unix bằng cách sử dụng strace:

sudo strace -fp PID 

Một lừa hacky có thể để thực hiện lệnh và ngay sau đó gắn vào quá trình này.Dưới đây là một số ví dụ:

sudo true; (./Pages &); sudo dtruss -fp `pgrep -n -x Pages` 
sudo true; (sleep 1 &); sudo dtruss -fp `pgrep -n -x sleep` 
sudo true; (tail -f /var/log/system.log &); sudo dtruss -fp `pgrep -n -x tail` 

Lưu ý:

  • sudo đầu tiên chỉ dành cho bộ nhớ đệm mật khẩu lúc đầu chạy,

  • thủ thuật này không làm việc cho lệnh nhanh chóng các dòng như ls, date vì phải mất một chút thời gian cho đến khi trình gỡ lỗi sẽ đính kèm vào quá trình,

  • bạn phải nhập lệnh của mình bằng hai pla ces,

  • bạn có thể bỏ qua & để chạy quá trình này để nền, nếu nó đã làm điều đó,

  • sau khi kết thúc gỡ lỗi, bạn sẽ phải tự giết chết quá trình nền (ví dụ killall -v tail)

+5

Bạn là một rockstar để chỉ ra tùy chọn '-n' cho dtruss. Đây là câu trả lời đúng 100%. – wfaulk

7

Các -n lập luận để dtruss sẽ gây dtruss chờ đợi và kiểm tra các quy trình phù hợp với lập luận để -n. Tùy chọn -f sẽ vẫn hoạt động để thực hiện theo các quy trình được chia tách từ các quy trình phù hợp với -n.

Tất cả điều này có nghĩa là nếu bạn muốn dtruss một quá trình (vì lợi ích của đối số, giả sử nó whoami) chạy như người dùng nonprivileged của bạn, hãy làm theo các bước sau:

  1. mở một vỏ rễ
  2. chạy dtruss -fn whoami
    • này sẽ ngồi và chờ cho một quá trình có tên "whoami" để tồn tại
  3. mở nonprivilege d vỏ
  4. Run whoami
    • này sẽ thực hiện và thoát thường
  5. Quan sát hệ thống gọi dấu vết trong cửa sổ dtruss
    • dtruss sẽ không đi theo lối riêng của mình - nó sẽ tiếp tục chờ đợi cho phù hợp với các quy trình - để thoát ra khỏi nó khi bạn hoàn thành

Câu trả lời này sao chép phần sau của câu trả lời @ kenorb, nhưng nó xứng đáng là câu trả lời đầu tiên.

3

Dường như OS X không hỗ trợ sử dụng dtrace để nhân rộng tất cả các tính năng của đường viền mà bạn cần. Tuy nhiên, tôi khuyên bạn nên cố gắng tạo một wrapper quanh các syscalls phù hợp. Có vẻ như DYLD_INSERT_LIBRARIES là biến môi trường bạn muốn hack một chút. Về cơ bản, nó giống như LD_PRELOAD cho Linux.

Một cách dễ dàng hơn nhiều làm chức năng thư viện ghi đè lên đang sử dụng biến DYLD_INSERT_LIBRARIES môi trường (tương tự như LD_PRELOAD trên Linux). Khái niệm rất đơn giản: tại thời điểm tải, trình liên kết động (dyld) sẽ tải bất kỳ thư viện động nào được chỉ định trong DYLD_INSERT_LIBRARIES trước bất kỳ thư viện nào mà tệp thực thi muốn tải. Bằng cách đặt tên một hàm giống như một hàm trong thư viện, nó sẽ ghi đè mọi cuộc gọi đến bản gốc.

Chức năng gốc cũng được tải và có thể được truy xuất bằng cách sử dụng dlsym (RTLD_NEXT, “function_name”); chức năng. Điều này cho phép một phương thức đơn giản bao gồm các hàm thư viện hiện có.

Theo example bởi Tom Robinson bạn có thể cần phải thiết lập DYLD_FORCE_FLAT_NAMESPACE=1, quá.

Bản sao ví dụ ban đầu (lib_overrides.c) mà chỉ fopen ghi đè:

#include <stdio.h> 
#include <unistd.h> 
#include <dlfcn.h> 

// for caching the original fopen implementation 
FILE * (*original_fopen) (const char *, const char *) = NULL; 

// our fopen override implmentation 
FILE * fopen(const char * filename, const char * mode) 
{ 
    // if we haven’t already, retrieve the original fopen implementation 
    if (!original_fopen) 
     original_fopen = dlsym(RTLD_NEXT, "fopen"); 

    // do our own processing; in this case just print the parameters 
    printf("== fopen: {%s,%s} ==\n", filename, mode); 

    // call the original fopen with the same arugments 
    FILE* f = original_fopen(filename, mode); 

    // return the result 
    return f; 
} 

Cách sử dụng:

$ gcc -Wall -o lib_overrides.dylib -dynamiclib lib_overrides.c 
$ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=lib_overrides.dylib command-to-test 
2

Disclaimer: đây có nguồn gốc từ @ của answer kenorb. Nó có một số lợi thế mặc dù: PID là cụ thể hơn so với execname. Và chúng ta có thể thực hiện một quy trình ngắn ngủi chờ DTrace trước khi nó bắt đầu.

Đây là một chút đua conditiony, nhưng ...

Hãy nói rằng chúng ta muốn theo dõi cat /etc/hosts:

sudo true && \ 
(sleep 1; cat /etc/hosts) &; \ 
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $!; \ 
kill $! 

Chúng tôi sử dụng sudo true để đảm bảo rằng chúng tôi xóa dấu nhắc mật khẩu sudo trước khi chúng tôi bắt đầu chạy bất cứ điều gì thời gian nhạy cảm.

Chúng tôi bắt đầu quá trình nền ("đợi 1 giây, sau đó thực hiện điều gì đó thú vị"). Trong khi đó, chúng tôi bắt đầu DTrace. Chúng tôi đã thu thập PID của quy trình nền thành $!, vì vậy chúng tôi có thể chuyển cho DTrace dưới dạng arg.

kill $! chạy sau khi chúng tôi đóng DTrace. Không cần thiết cho ví dụ cat của chúng tôi (quá trình tự đóng), nhưng nó giúp chúng tôi kết thúc các quy trình nền dài chạy như ping. Việc chuyển -p $! tới DTrace là cách ưu tiên để thực hiện việc này, nhưng trên macOS dường như yêu cầu tệp thực thi được ký mã.


Điều khác bạn có thể làm là chạy lệnh trong một trình bao riêng biệt và bóc vỏ đó. Xem số answer của tôi.

Các vấn đề liên quan