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.
This commit is contained in:
Jesse Smith 2019-03-18 18:09:24 -03:00
parent e19b991bb0
commit 4e2ad6a698
3 changed files with 84 additions and 2 deletions

View File

@ -4,6 +4,11 @@ sysvinit (2.95) unreleased; urgency=low
* Fixed various typos and control codes in manual pages. * Fixed various typos and control codes in manual pages.
Patch provided by Bjarni Ingi Gislason. 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 sysvinit (2.94) released; urgency=low

View File

@ -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 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. program, in other words the calling shell or shell script.
.IP "-f \fIformat\fP" .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. 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" .SH "EXIT STATUS"
.TP .TP
.B 0 .B 0

View File

@ -985,6 +985,66 @@ void nsyslog(int pri, char *fmt, ...)
#define PIDOF_NETFS 0x04 #define PIDOF_NETFS 0x04
#define PIDOF_QUIET 0x08 #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. * Pidof functionality.
*/ */
@ -1119,7 +1179,22 @@ int main_pidof(int argc, char **argv)
if ( ~flags & PIDOF_QUIET ) { if ( ~flags & PIDOF_QUIET ) {
if (format) 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 else
{ {
if (! first) if (! first)