From acbe9118ce8086f765ffb0da15f80c7c01a8903a Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Tue, 31 Oct 2017 14:24:19 -0400 Subject: [PATCH 1/4] ip netns: use strtol() instead of atoi() Use strtol-based API to parse and validate integer input; atoi() does not detect errors and may yield undefined behaviour if result can't be represented. v2: use get_unsigned() since network namespace is really an unsigned value. Signed-off-by: Roman Mashak --- ip/ipnetns.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index afb4978a..bad79331 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -700,7 +700,8 @@ static int netns_set(int argc, char **argv) { char netns_path[PATH_MAX]; const char *name; - int netns, nsid; + unsigned int nsid; + int netns; if (argc < 1) { fprintf(stderr, "No netns name specified\n"); @@ -711,7 +712,8 @@ static int netns_set(int argc, char **argv) return -1; } name = argv[0]; - nsid = atoi(argv[1]); + if (get_unsigned(&nsid, argv[1], 0)) + invarg("Invalid \"netnsid\" value\n", argv[1]); snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); netns = open(netns_path, O_RDONLY | O_CLOEXEC); From 38509fa903d66cf13f3c8ca5010db820fb874064 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Tue, 31 Oct 2017 18:47:54 +0100 Subject: [PATCH 2/4] ss: Remove useless width specifier in process context print Both local address and service, and remote address and service fields are already printed out in netlink_show_one() before we start printing process context, by calling sock_addr_print() twice. At this point, sock_addr_print() has already forced the remote service field to be 'serv_width' wide -- that is, 'serv_width' width has already been consumed, before we print process context. Hence, it makes no sense to force the display width of process context to be 'serv_width' wide again: previous prints have filled up the line already. Remove the width specifier and prefix with a space instead, to keep this consistent with fields which are displayed after the first output line. Signed-off-by: Stefano Brivio --- misc/ss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index dfb438f9..fa026eb0 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -3594,10 +3594,10 @@ static int netlink_show_one(struct filter *f, getpidcon(pid, &pid_context); if (pid_context != NULL) { - printf("proc_ctx=%-*s ", serv_width, pid_context); + printf(" proc_ctx=%s", pid_context); free(pid_context); } else { - printf("proc_ctx=%-*s ", serv_width, "unavailable"); + printf(" proc_ctx=unavailable"); } } From 22658ff53ab184bf446959fa0389717e82406b0d Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Tue, 31 Oct 2017 18:47:55 +0100 Subject: [PATCH 3/4] ss: Streamline process context printing in netlink_show_one() There's no need to check 'pid_context' before calling free(). Signed-off-by: Stefano Brivio --- misc/ss.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index fa026eb0..fb80d841 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -3593,12 +3593,8 @@ static int netlink_show_one(struct filter *f, else if (pid > 0) getpidcon(pid, &pid_context); - if (pid_context != NULL) { - printf(" proc_ctx=%s", pid_context); - free(pid_context); - } else { - printf(" proc_ctx=unavailable"); - } + printf(" proc_ctx=%s", pid_context ? : "unavailable"); + free(pid_context); } if (show_details) { From 4357f5c31af4d945ab05fa3ab57f56eb5b2d2ad4 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Tue, 31 Oct 2017 18:47:56 +0100 Subject: [PATCH 4/4] ss: Fix width calculations when Netid or State columns are missing If Netid or State columns are missing, we must not subtract one for each of these two columns from the remaining screen width, while distributing available space to columns. This one character corresponding to one delimiting space has to be subtracted only if the columns are actually printed. Further, in the existing implementation, if the screen width is an odd number, one additional character is added to the width of one of the two columns. But if both are not printed, this filling character needs to be added somewhere else, in order to have the right spacing allowing us to fill lines completely. Address and port fields are printed in pairs (local and remote), so we can't distribute the space to any of them, because it would be doubled. Instead, print this additional space to the right of the Send-Q column, to keep code changes to a minimum. This is particularly visible with 'ss -f netlink -Z'. Before this patch, with an 80 column terminal, we have: $ ss -f netlink -Z|head -n3 Recv-Q Send-Q Local Address:Port Peer Address:Port 0 0 rtnl:evolution-calen/2049 * pr oc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 0 0 rtnl:clock-applet/1944 * pr oc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 and with an 81 column terminal: $ ss -f netlink -Z|head -n3 Recv-Q Send-Q Local Address:Port Peer Address:Port 0 0 rtnl:evolution-calen/2049 * pro c_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 0 0 rtnl:clock-applet/1944 * pro c_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 After this patch, in both cases, the output is: $ ss -f netlink -Z|head -n3 Recv-Q Send-Q Local Address:Port Peer Address:Port 0 0 rtnl:evolution-calen/2049 * proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 0 0 rtnl:clock-applet/1944 * proc_ctx=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Signed-off-by: Stefano Brivio --- misc/ss.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index fb80d841..56a9ad41 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -107,6 +107,7 @@ int netid_width; int state_width; int addr_width; int serv_width; +char *odd_width_pad = ""; static const char *TCP_PROTO = "tcp"; static const char *SCTP_PROTO = "sctp"; @@ -838,7 +839,7 @@ static void sock_state_print(struct sockstat *s) printf("%-*s ", state_width, sstate_name[s->state]); } - printf("%-6d %-6d ", s->rq, s->wq); + printf("%-6d %-6d %s", s->rq, s->wq, odd_width_pad); } static void sock_details_print(struct sockstat *s) @@ -4364,8 +4365,10 @@ int main(int argc, char *argv[]) } addrp_width = screen_width; - addrp_width -= netid_width+1; - addrp_width -= state_width+1; + if (netid_width) + addrp_width -= netid_width + 1; + if (state_width) + addrp_width -= state_width + 1; addrp_width -= 14; if (addrp_width&1) { @@ -4373,6 +4376,8 @@ int main(int argc, char *argv[]) netid_width++; else if (state_width) state_width++; + else + odd_width_pad = " "; } addrp_width /= 2; @@ -4390,7 +4395,7 @@ int main(int argc, char *argv[]) printf("%-*s ", netid_width, "Netid"); if (state_width) printf("%-*s ", state_width, "State"); - printf("%-6s %-6s ", "Recv-Q", "Send-Q"); + printf("%-6s %-6s %s", "Recv-Q", "Send-Q", odd_width_pad); } /* Make enough space for the local/remote port field */