diff --git a/doc/Changelog b/doc/Changelog index 50e67e7..488baa4 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,9 @@ sysvinit (2.89dsf) UNRELEASED; urgency=low [ Werner Fink ] + * Fix counting message lines in wall. Patch from Petr Lautrbach. + * Fix bad printf conversion specifier in wall. Patch from Sébastien Luttringer. + * Add patches from Openwall project. Thanks goes to Solar Designer. * Add code to detect the system consoles with the help of the new /proc/consoles files of linux kernel 2.6.38+ * Try to make utmpdump IPv6 valid, change based on suggestion from diff --git a/src/bootlogd.c b/src/bootlogd.c index 3a12f3d..9343997 100644 --- a/src/bootlogd.c +++ b/src/bootlogd.c @@ -108,7 +108,7 @@ void handler(int sig) /* * Scan /dev and find the device name. */ -static int findtty(char *res, const char *startdir, int rlen, dev_t dev) +static int findtty(char *res, const char *startdir, size_t rlen, dev_t dev) { DIR *dir; struct dirent *ent; @@ -145,7 +145,7 @@ static int findtty(char *res, const char *startdir, int rlen, dev_t dev) if (!S_ISCHR(st.st_mode)) continue; if (st.st_rdev == dev) { - if ( (int) (strlen(ent->d_name) + strlen(startdir) + 1) >= rlen) { + if ( (strlen(ent->d_name) + strlen(startdir) + 1) >= rlen) { fprintf(stderr, "bootlogd: console device name too long\n"); closedir(dir); chdir(olddir); @@ -208,7 +208,7 @@ int findpty(int *master, int *slave, char *name) * See if a console taken from the kernel command line maps * to a character device we know about, and if we can open it. */ -int isconsole(char *s, char *res, int rlen) +int isconsole(char *s, char *res, size_t rlen) { struct consdev *c; int l, sl, i, fd; @@ -238,7 +238,7 @@ int isconsole(char *s, char *res, int rlen) * Find out the _real_ console. Assume that stdin is connected to * the console device (/dev/console). */ -int consolename(char *res, int rlen) +int consolename(char *res, size_t rlen) { #ifdef TIOCGDEV unsigned int kdev; diff --git a/src/halt.c b/src/halt.c index 499e973..5b9430c 100644 --- a/src/halt.c +++ b/src/halt.c @@ -239,7 +239,10 @@ int main(int argc, char **argv) exit(1); } - (void)chdir("/"); + if (chdir("/")) { + fprintf(stderr, "%s: chdir(/): %m\n", progname); + exit(1); + } if (!do_hard && !do_nothing) { /* diff --git a/src/init.c b/src/init.c index 7d3827c..d379fb2 100644 --- a/src/init.c +++ b/src/init.c @@ -89,6 +89,7 @@ /* Set a signal handler. */ #define SETSIG(sa, sig, fun, flags) \ do { \ + memset(&sa, 0, sizeof(sa)); \ sa.sa_handler = fun; \ sa.sa_flags = flags; \ sigemptyset(&sa.sa_mask); \ @@ -809,6 +810,24 @@ void console_stty(void) (void) close(fd); } +static ssize_t +safe_write(int fd, const char *buffer, size_t count) +{ + ssize_t offset = 0; + + while (count > 0) { + ssize_t block = write(fd, &buffer[offset], count); + + if (block < 0 && errno == EINTR) + continue; + if (block <= 0) + return offset ? offset : block; + offset += block; + count -= block; + } + return offset; +} + /* * Print to the system console */ @@ -817,7 +836,7 @@ void print(char *s) int fd; if ((fd = console_open(O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) { - write(fd, s, strlen(s)); + safe_write(fd, s, strlen(s)); close(fd); } } @@ -1669,9 +1688,9 @@ int ask_runlevel(void) if (fd < 0) return('S'); while(!strchr("0123456789S", lvl)) { - write(fd, prompt, sizeof(prompt) - 1); - buf[0] = 0; - read(fd, buf, sizeof(buf)); + safe_write(fd, prompt, sizeof(prompt) - 1); + if (read(fd, buf, sizeof(buf)) <= 0) + buf[0] = 0; if (buf[0] != 0 && (buf[1] == '\r' || buf[1] == '\n')) lvl = buf[0]; if (islower(lvl)) lvl = toupper(lvl); @@ -1956,12 +1975,15 @@ int make_pipe(int fd) { int fds[2]; - pipe(fds); + if (pipe(fds)) { + initlog(L_VB, "pipe: %m"); + return -1; + } dup2(fds[0], fd); close(fds[0]); fcntl(fds[1], F_SETFD, 1); fcntl(fd, F_SETFD, 0); - write(fds[1], Signature, 8); + safe_write(fds[1], Signature, 8); return fds[1]; } @@ -1991,7 +2013,10 @@ void re_exec(void) /* * construct a pipe fd --> STATE_PIPE and write a signature */ - fd = make_pipe(STATE_PIPE); + if ((fd = make_pipe(STATE_PIPE)) < 0) { + sigprocmask(SIG_SETMASK, &oldset, NULL); + initlog(L_CO, "Attempt to re-exec failed"); + } /* * It's a backup day today, so I'm pissed off. Being a BOFH, however, @@ -2033,10 +2058,10 @@ void re_exec(void) * We shouldn't be here, something failed. * Bitch, close the state pipe, unblock signals and return. */ + init_freeenv(env); close(fd); close(STATE_PIPE); sigprocmask(SIG_SETMASK, &oldset, NULL); - init_freeenv(env); initlog(L_CO, "Attempt to re-exec failed"); } @@ -2406,8 +2431,8 @@ void process_signals() /* See _what_ kind of SIGPWR this is. */ pwrstat = 0; if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) { - c = 0; - read(fd, &c, 1); + if (read(fd, &c, 1) != 1) + c = 0; pwrstat = c; close(fd); unlink(PWRSTAT); @@ -2415,8 +2440,8 @@ void process_signals() /* Path changed 2010-03-20. Look for the old path for a while. */ initlog(L_VB, "warning: found obsolete path %s, use %s instead", PWRSTAT_OLD, PWRSTAT); - c = 0; - read(fd, &c, 1); + if (read(fd, &c, 1) != 1) + c = 0; pwrstat = c; close(fd); unlink(PWRSTAT_OLD); @@ -2533,7 +2558,7 @@ void init_main(void) while((rc = wait(&st)) != f) if (rc < 0 && errno == ECHILD) break; - write(1, killmsg, sizeof(killmsg) - 1); + safe_write(1, killmsg, sizeof(killmsg) - 1); while(1) pause(); } #endif @@ -2808,7 +2833,7 @@ int main(int argc, char **argv) p = argv[0]; /* Common umask */ - umask(022); + umask(umask(077) | 022); /* Quick check */ if (geteuid() != 0) { diff --git a/src/killall5.c b/src/killall5.c index 7d753bd..3d35364 100644 --- a/src/killall5.c +++ b/src/killall5.c @@ -75,6 +75,7 @@ char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl"; /* Info about a process. */ typedef struct proc { + char *pathname; /* full path to executable */ char *argv0; /* Name as found out from argv[0] */ char *argv0base; /* `basename argv[1]` */ char *argv1; /* Name as found out from argv[1] */ @@ -206,8 +207,8 @@ int mount_proc(void) } if (pid == 0) { /* Try a few mount binaries. */ - execv("/sbin/mount", args); execv("/bin/mount", args); + execv("/sbin/mount", args); /* Okay, I give up. */ nsyslog(LOG_ERR, "cannot execute mount"); @@ -486,6 +487,7 @@ int readproc(int do_stat) if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); if (p->statname) free(p->statname); + free(p->pathname); free(p); } plist = NULL; @@ -505,13 +507,21 @@ int readproc(int do_stat) /* Read SID & statname from it. */ if ((fp = fopen(path, "r")) != NULL) { - buf[0] = 0; - fgets(buf, sizeof(buf), fp); + if (!fgets(buf, sizeof(buf), fp)) + buf[0] = '\0'; + + if (buf[0] == '\0') { + nsyslog(LOG_ERR, + "can't read from %s\n", path); + fclose(fp); + free(p); + continue; + } /* See if name starts with '(' */ s = buf; - while (*s != ' ') s++; - s++; + while (*s && *s != ' ') s++; + if (*s) s++; if (*s == '(') { /* Read program name. */ q = strrchr(buf, ')'); @@ -520,18 +530,20 @@ int readproc(int do_stat) nsyslog(LOG_ERR, "can't get program name from /proc/%s\n", path); + fclose(fp); if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); if (p->statname) free(p->statname); + free(p->pathname); free(p); continue; } s++; } else { q = s; - while (*q != ' ') q++; + while (*q && *q != ' ') q++; } - *q++ = 0; + if (*q) *q++ = 0; while (*q == ' ') q++; p->statname = (char *)xmalloc(strlen(s)+1); strcpy(p->statname, s); @@ -546,9 +558,11 @@ int readproc(int do_stat) p->sid = 0; nsyslog(LOG_ERR, "can't read sid from %s\n", path); + fclose(fp); if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); if (p->statname) free(p->statname); + free(p->pathname); free(p); continue; } @@ -560,6 +574,7 @@ int readproc(int do_stat) if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); if (p->statname) free(p->statname); + free(p->pathname); free(p); continue; } @@ -607,6 +622,7 @@ int readproc(int do_stat) if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); if (p->statname) free(p->statname); + free(p->pathname); free(p); continue; } @@ -623,6 +639,16 @@ int readproc(int do_stat) case DO_STAT: if (stat(path, &st) != 0) break; + else { + char buf[PATH_MAX]; + + f = readlink(path, buf, sizeof buf); + if (f > 0) { + p->pathname = (char *)xmalloc(f + 1); + memcpy(p->pathname, buf, f); + p->pathname[f] = '\0'; + } + } p->dev = st.st_dev; p->ino = st.st_ino; default: @@ -761,6 +787,20 @@ PIDQ_HEAD *pidof(char *prog) /* If we didn't find a match based on dev/ino, try the name. */ if (!foundone) for (p = plist; p; p = p->next) { + if (prog[0] == '/') { + if (!p->pathname) + continue; + if (strcmp(prog, p->pathname)) { + int len = strlen(prog); + if (strncmp(prog, p->pathname, len)) + continue; + if (strcmp(" (deleted)", p->pathname + len)) + continue; + } + add_pid_to_q(q, p); + continue; + } + ok = 0; /* matching nonmatching diff --git a/src/shutdown.c b/src/shutdown.c index 7e997da..384b4ff 100644 --- a/src/shutdown.c +++ b/src/shutdown.c @@ -154,7 +154,7 @@ int init_setenv(char *name, char *value) struct init_request request; struct sigaction sa; int fd; - int nl, vl; + size_t nl, vl; memset(&request, 0, sizeof(request)); request.magic = INIT_MAGIC; @@ -286,7 +286,8 @@ int spawn(int noerr, char *prog, ...) argv[i] = NULL; va_end(ap); - chdir("/"); + if (chdir("/")) + exit(1); environ = clean_env; execvp(argv[0], argv); @@ -627,7 +628,8 @@ int main(int argc, char **argv) /* Read pid of running shutdown from a file */ if ((fp = fopen(SDPID, "r")) != NULL) { - fscanf(fp, "%d", &pid); + if (fscanf(fp, "%d", &pid) != 1) + pid = 0; fclose(fp); } @@ -692,6 +694,12 @@ int main(int argc, char **argv) break; } + /* Go to the root directory */ + if (chdir("/")) { + fprintf(stderr, "shutdown: chdir(/): %m\n"); + exit(1); + } + /* Create a new PID file. */ unlink(SDPID); umask(022); @@ -715,8 +723,6 @@ int main(int argc, char **argv) sa.sa_handler = stopit; sigaction(SIGINT, &sa, NULL); - /* Go to the root directory */ - chdir("/"); if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644)); if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644)); diff --git a/src/wall.c b/src/wall.c index 92d9fb4..e480eee 100644 --- a/src/wall.c +++ b/src/wall.c @@ -102,14 +102,14 @@ int main(int argc, char **argv) i = 0; for (p = buf; *p; p++) { - if (*p == '\n' && i++ > MAXLINES) { + if (*p == '\n' && ++i >= MAXLINES) { *++p = 0; break; } } openlog("wall", LOG_PID, LOG_USER); - syslog(LOG_INFO, "wall: user %s broadcasted %d lines (%d chars)", + syslog(LOG_INFO, "wall: user %s broadcasted %d lines (%zu chars)", whoami, i, strlen(buf)); closelog();