Changed the way the "when" variable is used internally in shutdown.c.

It starts as a NULL pointer, then might get set as a pointer to optarg,
then it might get set to point to an argv parameter, then it might have
a string value copied into it, over-writing the original data. We should
not risk over-writing internal variables which might get used for something
else (it's rude and security risk). Set up "when" as its own buffer
that has data from optargs and/or argv copied into it.

Minor code fixes across multiple source files to avoid buffer
overflows, or uninitialized strings.
This commit is contained in:
Jesse Smith 2019-01-27 15:55:08 -04:00
parent 43b5c64126
commit 483dc777d2
6 changed files with 52 additions and 24 deletions

View File

@ -21,6 +21,17 @@ sysvinit (2.94) unreleased; urgency=low
* Added logsave.c and logsave.8 manual page from e2fsprogs to make * Added logsave.c and logsave.8 manual page from e2fsprogs to make
sure logsave is available to initscripts. sure logsave is available to initscripts.
* Updated src/Makefile to make sure bootlogd compiles with Clang. * Updated src/Makefile to make sure bootlogd compiles with Clang.
* Use defined constants for password length in sulogin. Makes
it easier to update/patch later.
* Minor code fixes across multiple source files to avoid buffer
overflows, or uninitialized strings.
* Changed the way the "when" variable is used internally in shutdown.c.
It starts as a NULL pointer, then might get set as a pointer to optarg,
then it might get set to point to an argv parameter, then it might have
a string value copied into it, over-writing the original data. We should
not risk over-writing internal variables which might get used for something
else (it's rude and security risk). Set up "when" as its own buffer
that has data from optargs and/or argv copied into it.
sysvinit (2.93) released; urgency=low sysvinit (2.93) released; urgency=low

View File

@ -433,7 +433,11 @@ int check4nfs(const char * path, char * real)
} while (1); } while (1);
if (real) strcpy(real, curr); if (real) /* real is defined elsewhere as being PATH_MAX + 1 */
{
memset(real, '\0', PATH_MAX + 1);
strncpy(real, curr, PATH_MAX);
}
if (errno == EINVAL) { if (errno == EINVAL) {
const size_t nlen = strlen(curr); const size_t nlen = strlen(curr);

View File

@ -48,6 +48,10 @@
# define SHUTDOWN_TIME 254 # define SHUTDOWN_TIME 254
#endif #endif
#ifndef PATH_MAX
#define PATH_MAX 2048
#endif
char *Version = "@(#) last 2.85 31-Apr-2004 miquels"; char *Version = "@(#) last 2.85 31-Apr-2004 miquels";
#define CHOP_DOMAIN 0 /* Define to chop off local domainname. */ #define CHOP_DOMAIN 0 /* Define to chop off local domainname. */
@ -253,10 +257,11 @@ int uread(FILE *fp, struct utmp *u, int *quit)
#define BTMP_FILE getbtmp() #define BTMP_FILE getbtmp()
char *getbtmp() char *getbtmp()
{ {
static char btmp[128]; static char btmp[PATH_MAX + 5]; /* max path + btmp + null terminator */
char *p; char *p;
strcpy(btmp, WTMP_FILE); memset(btmp, '\0', PATH_MAX + 5);
strncpy(btmp, WTMP_FILE, PATH_MAX);
if ((p = strrchr(btmp, '/')) == NULL) if ((p = strrchr(btmp, '/')) == NULL)
p = btmp; p = btmp;
else else
@ -841,7 +846,7 @@ int main(int argc, char **argv)
switch (ut.ut_type) { switch (ut.ut_type) {
case SHUTDOWN_TIME: case SHUTDOWN_TIME:
if (extended) { if (extended) {
strcpy(ut.ut_line, "system down"); strncpy(ut.ut_line, "system down", OLD_LINESIZE - 1);
quit = list(&ut, lastboot, R_NORMAL); quit = list(&ut, lastboot, R_NORMAL);
} }
lastdown = lastrch = ut.ut_time; lastdown = lastrch = ut.ut_time;
@ -850,14 +855,14 @@ int main(int argc, char **argv)
case OLD_TIME: case OLD_TIME:
case NEW_TIME: case NEW_TIME:
if (extended) { if (extended) {
strcpy(ut.ut_line, strncpy(ut.ut_line,
ut.ut_type == NEW_TIME ? "new time" : ut.ut_type == NEW_TIME ? "new time" :
"old time"); "old time", OLD_LINESIZE - 1);
quit = list(&ut, lastdown, R_TIMECHANGE); quit = list(&ut, lastdown, R_TIMECHANGE);
} }
break; break;
case BOOT_TIME: case BOOT_TIME:
strcpy(ut.ut_line, "system boot"); strncpy(ut.ut_line, "system boot", OLD_LINESIZE - 1);
quit = list(&ut, lastdown, R_REBOOT); quit = list(&ut, lastdown, R_REBOOT);
lastboot = ut.ut_time; lastboot = ut.ut_time;
down = 1; down = 1;

View File

@ -282,7 +282,7 @@ int main(int argc, char **argv)
outfn = argv[optind]; outfn = argv[optind];
optind++; optind++;
argv += optind; argv += optind;
argc -= optind; /* argc -= optind; - this is not used */
outfd = open(outfn, openflags, 0644); outfd = open(outfn, openflags, 0644);
do_stdin = !strcmp(argv[0], "-"); do_stdin = !strcmp(argv[0], "-");

View File

@ -32,6 +32,10 @@
#include <getopt.h> #include <getopt.h>
#include <stdio.h> #include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX 2048
#endif
int dostat(char *path, struct stat *st, int do_lstat, int quiet) int dostat(char *path, struct stat *st, int do_lstat, int quiet)
{ {
int n; int n;
@ -105,7 +109,7 @@ void usage(void) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct stat st, st2; struct stat st, st2;
char buf[256]; char buf[PATH_MAX + 1];
char *path; char *path;
int quiet = 0; int quiet = 0;
int showdev = 0; int showdev = 0;
@ -163,7 +167,7 @@ int main(int argc, char **argv)
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
strncpy(buf, path, sizeof(buf) - 4); strncpy(buf, path, sizeof(buf) - 4);
strcat(buf, "/.."); strncat(buf, "/..", 3);
if (dostat(buf, &st2, 0, quiet) < 0) if (dostat(buf, &st2, 0, quiet) < 0)
return 1; return 1;

View File

@ -70,6 +70,8 @@ extern char **environ;
#endif #endif
#define MESSAGELEN 256 #define MESSAGELEN 256
#define STATELEN 64
#define WHEN_SIZE 64
/* Whether we should warn system is shutting down */ /* Whether we should warn system is shutting down */
#define QUIET_FULL 2 #define QUIET_FULL 2
@ -83,7 +85,7 @@ int fastboot = 0; /* Do a 'fast' reboot */
int forcefsck = 0; /* Force fsck on reboot */ int forcefsck = 0; /* Force fsck on reboot */
char message[MESSAGELEN]; /* Warning message */ char message[MESSAGELEN]; /* Warning message */
char *sltime = 0; /* Sleep time */ char *sltime = 0; /* Sleep time */
char newstate[64]; /* What are we gonna do */ char newstate[STATELEN]; /* What are we gonna do */
int doself = 0; /* Don't use init */ int doself = 0; /* Don't use init */
int got_alrm = 0; int got_alrm = 0;
@ -232,11 +234,11 @@ int init_setenv(char *name, char *value)
*/ */
void issue_warn(int mins) void issue_warn(int mins)
{ {
char buf[MESSAGELEN + sizeof(newstate)]; char buf[MESSAGELEN + sizeof(newstate) + 1];
int len; int len;
buf[0] = 0; buf[0] = 0;
strncat(buf, message, sizeof(buf) - 1); strncpy(buf, message, MESSAGELEN);
len = strlen(buf); len = strlen(buf);
if (mins == 0) if (mins == 0)
@ -519,7 +521,7 @@ int main(int argc, char **argv)
char buf[128]; char buf[128];
char term[UT_LINESIZE + 6]; char term[UT_LINESIZE + 6];
char *sp; char *sp;
char *when = NULL; char when[WHEN_SIZE];
int c, i, wt; int c, i, wt;
int hours, mins; int hours, mins;
int didnolog = 0; int didnolog = 0;
@ -547,6 +549,7 @@ int main(int argc, char **argv)
} }
strcpy(down_level, "1"); strcpy(down_level, "1");
halttype = NULL; halttype = NULL;
memset(when, '\0', WHEN_SIZE);
/* Process the options. */ /* Process the options. */
while((c = getopt(argc, argv, "HPacqQkrhnfFyt:g:i:")) != EOF) { while((c = getopt(argc, argv, "HPacqQkrhnfFyt:g:i:")) != EOF) {
@ -593,7 +596,7 @@ int main(int argc, char **argv)
case 'y': /* Ignored for sysV compatibility */ case 'y': /* Ignored for sysV compatibility */
break; break;
case 'g': /* sysv style to specify time. */ case 'g': /* sysv style to specify time. */
when = optarg; strncpy(when, optarg, WHEN_SIZE - 1);
break; break;
case 'i': /* Level to go to. */ case 'i': /* Level to go to. */
if (!strchr("0156aAbBcCsS", optarg[0])) { if (!strchr("0156aAbBcCsS", optarg[0])) {
@ -679,7 +682,7 @@ int main(int argc, char **argv)
/* Read remaining words, skip time if needed. */ /* Read remaining words, skip time if needed. */
message[0] = 0; message[0] = 0;
for(c = optind + (!cancel && !when); c < argc; c++) { for(c = optind + (!cancel && !when[0]); c < argc; c++) {
if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN) if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
break; break;
strcat(message, argv[c]); strcat(message, argv[c]);
@ -704,9 +707,9 @@ int main(int argc, char **argv)
} }
/* Check syntax. */ /* Check syntax. */
if (when == NULL) { if (when[0] == '\0') {
if (optind == argc) usage(); if (optind == argc) usage();
when = argv[optind++]; strncpy(when, argv[optind++], WHEN_SIZE - 1);
} }
/* See if we are already running. */ /* See if we are already running. */
@ -725,16 +728,16 @@ int main(int argc, char **argv)
/* Tell users what we're gonna do. */ /* Tell users what we're gonna do. */
switch(down_level[0]) { switch(down_level[0]) {
case '0': case '0':
strcpy(newstate, "for system halt"); strncpy(newstate, "for system halt", STATELEN);
break; break;
case '6': case '6':
strcpy(newstate, "for reboot"); strncpy(newstate, "for reboot", STATELEN);
break; break;
case '1': case '1':
strcpy(newstate, "to maintenance mode"); strncpy(newstate, "to maintenance mode", STATELEN);
break; break;
default: default:
sprintf(newstate, "to runlevel %s", down_level); snprintf(newstate, STATELEN, "to runlevel %s", down_level);
break; break;
} }
@ -772,10 +775,11 @@ int main(int argc, char **argv)
/* Alias now and take care of old '+mins' notation. */ /* Alias now and take care of old '+mins' notation. */
if (!strcmp(when, "now")) strcpy(when, "0"); if (!strcmp(when, "now")) strcpy(when, "0");
if (when[0] == '+') when++;
sp = when;
if (when[0] == '+') sp++;
/* Decode shutdown time. */ /* Decode shutdown time. */
for (sp = when; *sp; sp++) { for ( ; *sp; sp++) {
if (*sp != ':' && (*sp < '0' || *sp > '9')) if (*sp != ':' && (*sp < '0' || *sp > '9'))
usage(); usage();
} }