From 4e2ad6a69847fd142b3497ffdc9ef1b74061d886 Mon Sep 17 00:00:00 2001 From: Jesse Smith Date: Mon, 18 Mar 2019 18:09:24 -0300 Subject: [PATCH] Fixed segfault in pidof when the -f (format) flag is used with crafted format strings. Avoid printing stack memory when special format string is passed to -f. Listed control characters for -f flag in manual page. --- doc/Changelog | 5 ++++ man/pidof.8 | 4 ++- src/killall5.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index dd55c30..b8ac41a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,11 @@ sysvinit (2.95) unreleased; urgency=low * Fixed various typos and control codes in manual pages. Patch provided by Bjarni Ingi Gislason. + * Patched pidof so that the -f flag does not print memory information + from the stack when passed a specially crafted format string. + Also prevent segfault when "%s" is used in a format string. + Special characters for the format string can be found in the man + page for pidof. sysvinit (2.94) released; urgency=low diff --git a/man/pidof.8 b/man/pidof.8 index a4295b9..4e83492 100644 --- a/man/pidof.8 +++ b/man/pidof.8 @@ -69,8 +69,10 @@ Tells \fIpidof\fP to omit processes with that process id. The special pid \fB%PPID\fP can be used to name the parent process of the \fIpidof\fP program, in other words the calling shell or shell script. .IP "-f \fIformat\fP" -Tells \fIpidof\fP to format the process ids in the given \fIprintf\fP style. +Tells \fIpidof\fP to format the process IDs in the given \fIprintf\fP style string. For example \fB" -p%d"\fP is useful for \fIstrace\fP. +The "%d" symbol is used as a place holder for the PID to be printed. A "\\n" can +be used to cause a newline to be printed. For example \fB" %d\\n"\fP. .SH "EXIT STATUS" .TP .B 0 diff --git a/src/killall5.c b/src/killall5.c index 8f2ad50..375b4a7 100644 --- a/src/killall5.c +++ b/src/killall5.c @@ -985,6 +985,66 @@ void nsyslog(int pri, char *fmt, ...) #define PIDOF_NETFS 0x04 #define PIDOF_QUIET 0x08 + +/* Replace elements (from) of the original string + with new elements (to). + Returns the new string on success or NULL on failure. + Free the returnedstring after use. +*/ +char *Replace_String(char *from, char *to, char *original) +{ + int from_length, to_length; + int source_length, destination_length; + int replace_count = 0; + char *replace_position; + char *destination_string; + char *source_position, *destination_position; + + if ( (! from) || (! to) || (! original) ) + return NULL; + + from_length = strlen(from); + to_length = strlen(to); + source_length = strlen(original); + replace_position = strstr(original, from); + /* There is nothing to replace, return original string */ + if (! replace_position) + return strdup(original); + /* count number of times we need to perform replacement */ + while (replace_position) + { + replace_count++; + replace_position++; + replace_position = strstr(replace_position, from); + } + /* calculate length and allocate the new string */ + destination_length = source_length + ( (to_length - from_length) * replace_count); + destination_string = calloc(destination_length, sizeof(char)); + if (! destination_string) + return NULL; + + /* Copy source string up to the part we need to replace. Then jump over the replaced bit */ + source_position = original; + destination_position = destination_string; + replace_position = strstr(original, from); + while (replace_position) + { + for ( ; source_position < replace_position; source_position++) + { + destination_position[0] = source_position[0]; + destination_position++; + } + strcat(destination_position, to); + source_position += from_length; + destination_position += to_length; + replace_position = strstr(source_position, from); + } + /* Replaced all the items, now copy the tail end of the original string */ + strcat(destination_position, source_position); + return destination_string; +} + + /* * Pidof functionality. */ @@ -1119,7 +1179,22 @@ int main_pidof(int argc, char **argv) if ( ~flags & PIDOF_QUIET ) { if (format) - printf(format, p->pid); + { + char *show_string, *final_string; + char my_pid[32]; + snprintf(my_pid, 32, "%d", p->pid); + show_string = Replace_String("%d", my_pid, format); + final_string = Replace_String("\\n", "\n", show_string); + if (show_string) free(show_string); + if (final_string) + { + printf("%s", final_string); + free(final_string); + } + else + fprintf(stderr, "Cannot handle format provided by -f\n"); + /* printf(format, p->pid); */ + } else { if (! first)