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
/*
* 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;
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);
* 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;
* 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;
exit(1);
}
- (void)chdir("/");
+ if (chdir("/")) {
+ fprintf(stderr, "%s: chdir(/): %m\n", progname);
+ exit(1);
+ }
if (!do_hard && !do_nothing) {
/*
/* 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); \
(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
*/
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);
}
}
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);
{
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];
}
/*
* 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,
* 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");
}
/* 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);
/* 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);
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
p = argv[0];
/* Common umask */
- umask(022);
+ umask(umask(077) | 022);
/* Quick check */
if (geteuid() != 0) {
/* 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] */
}
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");
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;
/* 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, ')');
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);
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;
}
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
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:
/* 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
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;
argv[i] = NULL;
va_end(ap);
- chdir("/");
+ if (chdir("/"))
+ exit(1);
environ = clean_env;
execvp(argv[0], 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);
}
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);
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));
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();