All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: netdev@vger.kernel.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
	Josiah Stearns <B00TK1D@proton.me>
Subject: [PATCH iproute2-next] ss: escape characters in command name
Date: Tue,  4 Feb 2025 08:24:16 -0800	[thread overview]
Message-ID: <20250204162429.17902-1-stephen@networkplumber.org> (raw)

Since the process name is under user control with prctl(PR_SET_NAME)
it may contain escape characters to try and mess with screen output.

Reuse the existing string logic from procps (used by ps command).

Reported-by: Josiah Stearns <B00TK1D@proton.me>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 include/utils.h |   2 +
 lib/Makefile    |   2 +-
 lib/escape.c    | 111 ++++++++++++++++++++++++++++++++++++++++++++++++
 misc/ss.c       |  10 ++---
 4 files changed, 119 insertions(+), 6 deletions(-)
 create mode 100644 lib/escape.c

diff --git a/include/utils.h b/include/utils.h
index 9a81494d..e91c5f0e 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -372,6 +372,8 @@ const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val);
 unsigned int get_str_char_count(const char *str, int match);
 int str_split_by_char(char *str, char **before, char **after, int match);
 
+int escape_str (char *dst, const char *src, int bufsize);
+
 #define INDENT_STR_MAXLEN 32
 
 struct indent_mem {
diff --git a/lib/Makefile b/lib/Makefile
index aa7bbd2e..c259722f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,7 +5,7 @@ CFLAGS += -fPIC
 
 UTILOBJ = utils.o utils_math.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \
 	inet_proto.o namespace.o json_writer.o json_print.o json_print_math.o \
-	names.o color.o bpf_legacy.o bpf_glue.o exec.o fs.o cg_map.o ppp_proto.o
+	names.o color.o bpf_legacy.o bpf_glue.o exec.o fs.o cg_map.o ppp_proto.o escape.o
 
 ifeq ($(HAVE_ELF),y)
 ifeq ($(HAVE_LIBBPF),y)
diff --git a/lib/escape.c b/lib/escape.c
new file mode 100644
index 00000000..b110f61b
--- /dev/null
+++ b/lib/escape.c
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Escape character print handling derived from procps
+ * Copyright 1998-2002 by Albert Cahalan
+ * Copyright 2020-2022 Jim Warner <james.warner@comcast.net>
+ *
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <langinfo.h>
+
+#include "utils.h"
+
+static const char UTF_tab[] = {
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x00 - 0x0F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x10 - 0x1F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x20 - 0x2F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x30 - 0x3F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x40 - 0x4F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x50 - 0x5F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x60 - 0x6F
+	1,  1,	1,  1,	1,  1,	1,  1,
+	1,  1,	1,  1,	1,  1,	1,  1, // 0x70 - 0x7F
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, // 0x80 - 0x8F
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, // 0x90 - 0x9F
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, // 0xA0 - 0xAF
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, // 0xB0 - 0xBF
+	-1, -1, 2,  2,	2,  2,	2,  2,
+	2,  2,	2,  2,	2,  2,	2,  2, // 0xC0 - 0xCF
+	2,  2,	2,  2,	2,  2,	2,  2,
+	2,  2,	2,  2,	2,  2,	2,  2, // 0xD0 - 0xDF
+	3,  3,	3,  3,	3,  3,	3,  3,
+	3,  3,	3,  3,	3,  3,	3,  3, // 0xE0 - 0xEF
+	4,  4,	4,  4,	4,  -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, // 0xF0 - 0xFF
+};
+
+static const unsigned char ESC_tab[] = {
+	"@..............................." // 0x00 - 0x1F
+	"||||||||||||||||||||||||||||||||" // 0x20 - 0x3F
+	"||||||||||||||||||||||||||||||||" // 0x40 - 0x5f
+	"|||||||||||||||||||||||||||||||." // 0x60 - 0x7F
+	"????????????????????????????????" // 0x80 - 0x9F
+	"????????????????????????????????" // 0xA0 - 0xBF
+	"????????????????????????????????" // 0xC0 - 0xDF
+	"????????????????????????????????" // 0xE0 - 0xFF
+};
+
+static void esc_all(unsigned char *str)
+{
+	// if bad locale/corrupt str, replace non-printing stuff
+	while (*str) {
+		unsigned char c = ESC_tab[*str];
+
+		if (c != '|')
+			*str = c;
+		++str;
+	}
+}
+
+static void esc_ctl(unsigned char *str, int len)
+{
+	int i;
+
+	for (i = 0; i < len;) {
+		// even with a proper locale, strings might be corrupt
+		int n = UTF_tab[*str];
+
+		if (n < 0 || i + n > len) {
+			esc_all(str);
+			return;
+		}
+		// and eliminate those non-printing control characters
+		if (*str < 0x20 || *str == 0x7f)
+			*str = '?';
+		str += n;
+		i += n;
+	}
+}
+
+int escape_str(char *dst, const char *src, int bufsize)
+{
+	static int utf_sw;
+
+	if (utf_sw == 0) {
+		char *enc = nl_langinfo(CODESET);
+
+		utf_sw = enc && strcasecmp(enc, "UTF-8") == 0 ? 1 : -1;
+	}
+
+	int n = strlcpy(dst, src, bufsize);
+
+	if (utf_sw < 0)
+		esc_all((unsigned char *)dst);
+	else
+		esc_ctl((unsigned char *)dst, n);
+	return n;
+}
diff --git a/misc/ss.c b/misc/ss.c
index aef1a714..1d70242e 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -550,8 +550,7 @@ static void user_ent_add(unsigned int ino, char *task,
 static void user_ent_hash_build_task(char *path, int pid, int tid)
 {
 	const char *no_ctx = "unavailable";
-	char task[16] = {'\0', };
-	char stat[MAX_PATH_LEN];
+	char task[20] = { };
 	int pos_id, pos_fd;
 	char *task_context;
 	struct dirent *d;
@@ -599,6 +598,8 @@ static void user_ent_hash_build_task(char *path, int pid, int tid)
 			sock_context = strdup(no_ctx);
 
 		if (task[0] == '\0') {
+			char stat[MAX_PATH_LEN];
+			char name[16];
 			FILE *fp;
 
 			strlcpy(stat, path, pos_id + 1);
@@ -606,9 +607,8 @@ static void user_ent_hash_build_task(char *path, int pid, int tid)
 
 			fp = fopen(stat, "r");
 			if (fp) {
-				if (fscanf(fp, "%*d (%[^)])", task) < 1) {
-					; /* ignore */
-				}
+				if (fscanf(fp, "%*d (%[^)])", name) == 1)
+					escape_str(task, name, sizeof(task));
 				fclose(fp);
 			}
 		}
-- 
2.47.2


             reply	other threads:[~2025-02-04 16:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-04 16:24 Stephen Hemminger [this message]
2026-02-04  9:01 ` [PATCH iproute2-next] ss: escape characters in command name Michal Kubecek
2026-02-04  9:21 ` Michal Kubecek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250204162429.17902-1-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --cc=B00TK1D@proton.me \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.