From 20061e8faec70c65507f4d50b73b542c7e0b9517 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 9 Apr 2021 19:24:12 +0200 Subject: [PATCH] tools/ttysnoop: Add --datasize/--datacount Adding the possibility to define transmitting data size (--datasize option) and number of times we ask for this amount (--datacount option). This helps to configure ttysnoop behaviour for the expected data in the terminal session. For example ncurses applications like mc or huge sized terminals need bigger buffer to snoop everything from the buffer. Signed-off-by: Jiri Olsa --- man/man8/ttysnoop.8 | 6 +++++ tools/ttysnoop.py | 46 ++++++++++++++++++++++++++------------ tools/ttysnoop_example.txt | 17 +++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/man/man8/ttysnoop.8 b/man/man8/ttysnoop.8 index 9f37aaa9..e2ec037f 100644 --- a/man/man8/ttysnoop.8 +++ b/man/man8/ttysnoop.8 @@ -20,6 +20,12 @@ CONFIG_BPF and bcc. \-C Don't clear the screen. .TP +\-s SIZE , \-\-datasize SIZE +Size of the transmitting buffer (default 256). +.TP +\-c COUNT, \-\-datacount COUNT +Number of times ttysnop checks for SIZE bytes of data (default 16). +.TP device Either a path to a tty device (eg, /dev/tty0) or a pts number (eg, the "3" from /dev/pts/3). diff --git a/tools/ttysnoop.py b/tools/ttysnoop.py index 1249f228..237f333c 100755 --- a/tools/ttysnoop.py +++ b/tools/ttysnoop.py @@ -28,10 +28,13 @@ def usage(): # arguments examples = """examples: - ./ttysnoop /dev/pts/2 # snoop output from /dev/pts/2 - ./ttysnoop 2 # snoop output from /dev/pts/2 (shortcut) - ./ttysnoop /dev/console # snoop output from the system console - ./ttysnoop /dev/tty0 # snoop output from /dev/tty0 + ./ttysnoop /dev/pts/2 # snoop output from /dev/pts/2 + ./ttysnoop 2 # snoop output from /dev/pts/2 (shortcut) + ./ttysnoop /dev/console # snoop output from the system console + ./ttysnoop /dev/tty0 # snoop output from /dev/tty0 + ./ttysnoop /dev/pts/2 -s 1024 # snoop output from /dev/pts/2 with data size 1024 + ./ttysnoop /dev/pts/2 -c 2 # snoop output from /dev/pts/2 with 2 checks for 256 bytes of data in buffer + (potentially retrieving 512 bytes) """ parser = argparse.ArgumentParser( description="Snoop output from a pts or tty device, eg, a shell", @@ -41,6 +44,10 @@ parser.add_argument("-C", "--noclear", action="store_true", help="don't clear the screen") parser.add_argument("device", default="-1", help="path to a tty device (eg, /dev/tty0) or pts number") +parser.add_argument("-s", "--datasize", default="256", + help="size of the transmitting buffer (default 256)") +parser.add_argument("-c", "--datacount", default="16", + help="number of times we check for 'data-size' data (default 16)") parser.add_argument("--ebpf", action="store_true", help=argparse.SUPPRESS) args = parser.parse_args() @@ -64,7 +71,7 @@ bpf_text = """ #include #include -#define BUFSIZE 256 +#define BUFSIZE USER_DATASIZE struct data_t { int count; char buf[BUFSIZE]; @@ -75,7 +82,7 @@ BPF_PERF_OUTPUT(events); static int do_tty_write(void *ctx, const char __user *buf, size_t count) { - int zero = 0; + int zero = 0, i; struct data_t *data; /* We can't read data to map data before v4.11 */ @@ -89,14 +96,22 @@ static int do_tty_write(void *ctx, const char __user *buf, size_t count) return 0; #endif - // bpf_probe_read_user() can only use a fixed size, so truncate to count - // in user space: - bpf_probe_read_user(&data->buf, BUFSIZE, (void *)buf); - if (count > BUFSIZE) - data->count = BUFSIZE; - else - data->count = count; - events.perf_submit(ctx, data, sizeof(*data)); + #pragma unroll + for (i = 0; i < USER_DATACOUNT; i++) { + // bpf_probe_read_user() can only use a fixed size, so truncate to count + // in user space: + if (bpf_probe_read_user(&data->buf, BUFSIZE, (void *)buf)) + return 0; + if (count > BUFSIZE) + data->count = BUFSIZE; + else + data->count = count; + events.perf_submit(ctx, data, sizeof(*data)); + if (count < BUFSIZE) + return 0; + count -= BUFSIZE; + buf += BUFSIZE; + } return 0; }; @@ -142,6 +157,9 @@ if debug or args.ebpf: if args.ebpf: exit() +bpf_text = bpf_text.replace('USER_DATASIZE', '%s' % args.datasize) +bpf_text = bpf_text.replace('USER_DATACOUNT', '%s' % args.datacount) + # initialize BPF b = BPF(text=bpf_text) diff --git a/tools/ttysnoop_example.txt b/tools/ttysnoop_example.txt index 1c299617..95dbf32e 100644 --- a/tools/ttysnoop_example.txt +++ b/tools/ttysnoop_example.txt @@ -73,11 +73,16 @@ positional arguments: device path to a tty device (eg, /dev/tty0) or pts number optional arguments: - -h, --help show this help message and exit - -C, --noclear don't clear the screen + -h, --help show this help message and exit + -C, --noclear don't clear the screen + -s, --datasize size of the transmitting buffer (default 256) + -c, --datacount number of times ttysnop checks for data (default 16) examples: - ./ttysnoop /dev/pts/2 # snoop output from /dev/pts/2 - ./ttysnoop 2 # snoop output from /dev/pts/2 (shortcut) - ./ttysnoop /dev/console # snoop output from the system console - ./ttysnoop /dev/tty0 # snoop output from /dev/tty0 + ./ttysnoop /dev/pts/2 # snoop output from /dev/pts/2 + ./ttysnoop 2 # snoop output from /dev/pts/2 (shortcut) + ./ttysnoop /dev/console # snoop output from the system console + ./ttysnoop /dev/tty0 # snoop output from /dev/tty0 + ./ttysnoop /dev/pts/2 -s 1024 # snoop output from /dev/pts/2 with data size 1024 + ./ttysnoop /dev/pts/2 -c 2 # snoop output from /dev/pts/2 with 2 checks for 256 bytes of data in buffer + (potentionaly retrieving 512 bytes) -- 2.34.1