From: "j.ps@openmailbox.org" <j.ps@openmailbox.org>
To: netdev@vger.kernel.org
Cc: stephen@networkplumber.org
Subject: Re: Segmentation fault in iproute2 ss -p (versions 4.0.0, 4.1.0 and 4.1.1)
Date: Mon, 20 Jul 2015 08:07:17 +0100 [thread overview]
Message-ID: <55AC9E25.9050804@openmailbox.org> (raw)
In-Reply-To: <20150719140548.6d17a475@urahara>
[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]
--- iproute2-4.1.1-orig/misc/ss.c 2015-07-06 22:57:34.000000000 +0100
+++ iproute2-4.1.1/misc/ss.c 2015-07-19 12:16:25.000000000 +0100
@@ -428,9 +428,12 @@
while (cnt != USER_ENT_HASH_SIZE) {
p = user_ent_hash[cnt];
while (p) {
- free(p->process);
- free(p->process_ctx);
- free(p->socket_ctx);
+ if (p->process)
+ free(p->process);
+ if (p->process_ctx)
+ free(p->process_ctx);
+ if (p->socket_ctx)
+ free(p->socket_ctx);
p_next = p->next;
free(p);
p = p_next;
@@ -456,7 +459,21 @@
user_ent_hash_build_init = 1;
- strcpy(name, root);
+ /* strcpy is really dangerous! in this case if we're going to
+ copy an unknown input size from getenv("PROC_ROOT") to a
+ fixed size buffer name[1024] we're going to get troubles.
+ If the size of a manipulated "PROC_ROOT" > size of name we
+ will have a buffer overrun smashing the stack, overwriting
+ other local variables and/or return address, etc... */
+
+ memset(name, 0, sizeof(name));
+
+ strncpy(name, root, 512);
+ /* Chose this value ^^^ (maybe too large) just to avoid buffer
+ overflow if sizeof getenv("PROC_ROOT") > sizeof(name) and
+ to allow the name composition that follows below to fit in
+ the remaining space. */
+
if (strlen(name) == 0 || name[strlen(name)-1] != '/')
strcat(name, "/");
@@ -480,7 +497,7 @@
if (getpidcon(pid, &pid_context) != 0)
pid_context = strdup(no_ctx);
- sprintf(name + nameoff, "%d/fd/", pid);
+ snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
pos = strlen(name);
if ((dir1 = opendir(name)) == NULL)
continue;
@@ -499,7 +516,7 @@
if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
continue;
- sprintf(name+pos, "%d", fd);
+ snprintf(name+pos, sizeof(name) - pos, "%d", fd);
link_len = readlink(name, lnk, sizeof(lnk)-1);
if (link_len == -1)
@@ -529,9 +546,16 @@
}
user_ent_add(ino, p, pid, fd,
pid_context, sock_context);
- free(sock_context);
- }
- free(pid_context);
+ /* memory was allocated conditionally so
+ freeing it should go the same way (even
+ though the actual code implies that in
+ this case it will always be allocated). */
+ if (sock_context)
+ free(sock_context);
+ }
+ /* same as above */
+ if (pid_context)
+ free(pid_context);
closedir(dir1);
}
closedir(dir);
@@ -2722,6 +2746,13 @@
if (!(u = malloc(sizeof(*u))))
break;
+ /* The following memset of 'u' struct is crucial to avoid a segfault
+ when freeing memory 'free(name)' at 'unix_list_free()'. In fact,
+ without this 'initialization', testing 'if (name)' at line 2513
+ will most likely return true even if 'name' isn't allocated. */
+
+ memset(u, 0, sizeof(*u));
+
if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
&u->rport, &u->rq, &u->wq, &flags, &u->type,
&u->state, &u->ino, name) < 8)
@@ -3064,11 +3095,12 @@
strncpy(procname, "kernel", 6);
} else if (pid > 0) {
FILE *fp;
- sprintf(procname, "%s/%d/stat",
+ snprintf(procname, sizeof(procname), "%s/%d/stat",
getenv("PROC_ROOT") ? : "/proc", pid);
if ((fp = fopen(procname, "r")) != NULL) {
if (fscanf(fp, "%*d (%[^)])", procname) == 1) {
- sprintf(procname+strlen(procname), "/%d", pid);
+ snprintf(procname+strlen(procname),
+ sizeof(procname)-strlen(procname), "/%d", pid);
done = 1;
}
fclose(fp);
-------- Forwarded Message --------
Subject: Re: Segmentation fault in iproute2 ss -p (versions 4.0.0, 4.1.0
and 4.1.1)
Date: Sun, 19 Jul 2015 14:05:48 -0700
From: Stephen Hemminger <stephen@networkplumber.org>
To: <j.ps@member.fsf.org>
Please send patches as plain text for review to netdev@vger.kernel.org
[-- Attachment #2: iproute2-4.1.1-patch --]
[-- Type: text/plain, Size: 3540 bytes --]
--- iproute2-4.1.1-orig/misc/ss.c 2015-07-06 22:57:34.000000000 +0100
+++ iproute2-4.1.1/misc/ss.c 2015-07-19 12:16:25.000000000 +0100
@@ -428,9 +428,12 @@
while (cnt != USER_ENT_HASH_SIZE) {
p = user_ent_hash[cnt];
while (p) {
- free(p->process);
- free(p->process_ctx);
- free(p->socket_ctx);
+ if (p->process)
+ free(p->process);
+ if (p->process_ctx)
+ free(p->process_ctx);
+ if (p->socket_ctx)
+ free(p->socket_ctx);
p_next = p->next;
free(p);
p = p_next;
@@ -456,7 +459,21 @@
user_ent_hash_build_init = 1;
- strcpy(name, root);
+ /* strcpy is really dangerous! in this case if we're going to
+ copy an unknown input size from getenv("PROC_ROOT") to a
+ fixed size buffer name[1024] we're going to get troubles.
+ If the size of a manipulated "PROC_ROOT" > size of name we
+ will have a buffer overrun smashing the stack, overwriting
+ other local variables and/or return address, etc... */
+
+ memset(name, 0, sizeof(name));
+
+ strncpy(name, root, 512);
+ /* Chose this value ^^^ (maybe too large) just to avoid buffer
+ overflow if sizeof getenv("PROC_ROOT") > sizeof(name) and
+ to allow the name composition that follows below to fit in
+ the remaining space. */
+
if (strlen(name) == 0 || name[strlen(name)-1] != '/')
strcat(name, "/");
@@ -480,7 +497,7 @@
if (getpidcon(pid, &pid_context) != 0)
pid_context = strdup(no_ctx);
- sprintf(name + nameoff, "%d/fd/", pid);
+ snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
pos = strlen(name);
if ((dir1 = opendir(name)) == NULL)
continue;
@@ -499,7 +516,7 @@
if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
continue;
- sprintf(name+pos, "%d", fd);
+ snprintf(name+pos, sizeof(name) - pos, "%d", fd);
link_len = readlink(name, lnk, sizeof(lnk)-1);
if (link_len == -1)
@@ -529,9 +546,16 @@
}
user_ent_add(ino, p, pid, fd,
pid_context, sock_context);
- free(sock_context);
- }
- free(pid_context);
+ /* memory was allocated conditionally so
+ freeing it should go the same way (even
+ though the actual code implies that in
+ this case it will always be allocated). */
+ if (sock_context)
+ free(sock_context);
+ }
+ /* same as above */
+ if (pid_context)
+ free(pid_context);
closedir(dir1);
}
closedir(dir);
@@ -2722,6 +2746,13 @@
if (!(u = malloc(sizeof(*u))))
break;
+ /* The following memset of 'u' struct is crucial to avoid a segfault
+ when freeing memory 'free(name)' at 'unix_list_free()'. In fact,
+ without this 'initialization', testing 'if (name)' at line 2513
+ will most likely return true even if 'name' isn't allocated. */
+
+ memset(u, 0, sizeof(*u));
+
if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
&u->rport, &u->rq, &u->wq, &flags, &u->type,
&u->state, &u->ino, name) < 8)
@@ -3064,11 +3095,12 @@
strncpy(procname, "kernel", 6);
} else if (pid > 0) {
FILE *fp;
- sprintf(procname, "%s/%d/stat",
+ snprintf(procname, sizeof(procname), "%s/%d/stat",
getenv("PROC_ROOT") ? : "/proc", pid);
if ((fp = fopen(procname, "r")) != NULL) {
if (fscanf(fp, "%*d (%[^)])", procname) == 1) {
- sprintf(procname+strlen(procname), "/%d", pid);
+ snprintf(procname+strlen(procname),
+ sizeof(procname)-strlen(procname), "/%d", pid);
done = 1;
}
fclose(fp);
next parent reply other threads:[~2015-07-20 7:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20150719140548.6d17a475@urahara>
2015-07-20 7:07 ` j.ps [this message]
2015-07-20 19:09 ` Segmentation fault in iproute2 ss -p (versions 4.0.0, 4.1.0 and 4.1.1) Stephen Hemminger
2015-07-21 9:50 ` j.ps
2015-07-21 9:54 ` "ss -p" segfaults j.ps
2015-10-06 10:09 ` "ss -p" segfaults (updated to 4.2) Willy Tarreau
2015-10-10 14:34 ` j.ps
2015-10-12 16:50 ` Stephen Hemminger
2015-10-12 16:55 ` Willy Tarreau
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=55AC9E25.9050804@openmailbox.org \
--to=j.ps@openmailbox.org \
--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;
as well as URLs for NNTP newsgroup(s).