From: Michal Kubecek <mkubecek@suse.cz>
To: Stephen Hemminger <stephen@networkplumber.org>, netdev@vger.kernel.org
Cc: Josiah Stearns <B00TK1D@proton.me>
Subject: [PATCH RESEND iproute2] ss: escape characters in command name
Date: Thu, 26 Mar 2026 00:03:02 +0100 [thread overview]
Message-ID: <20260325231911.E69172009B@lion.mk-sys.cz> (raw)
From: Stephen Hemminger <stephen@networkplumber.org>
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>
Reviewed-by: Michal Kubecek <mkubecek@suse.cz>
Tested-by: Michal Kubecek <mkubecek@suse.cz>
---
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 adf6a581a2a6..8b7e6d9e2c3b 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -369,6 +369,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 cd561bc09235..7035f40f8953 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -6,7 +6,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 bridge.o sha1.o
+ ppp_proto.o bridge.o sha1.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 000000000000..b110f61b3038
--- /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 28a82c669493..121ca6d55cb7 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.53.0
reply other threads:[~2026-03-25 23:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260325231911.E69172009B@lion.mk-sys.cz \
--to=mkubecek@suse.cz \
--cc=B00TK1D@proton.me \
--cc=netdev@vger.kernel.org \
--cc=stephen@networkplumber.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox