--- embedaddon/sudo/plugins/sudoers/iolog.c 2012/05/29 12:26:49 1.1.1.2 +++ embedaddon/sudo/plugins/sudoers/iolog.c 2012/10/09 09:29:52 1.1.1.3 @@ -135,7 +135,7 @@ mkdir_parents(char *path) * Uses file locking to avoid sequence number collisions. */ void -io_nextid(char *iolog_dir, char sessid[7]) +io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]) { struct stat sb; char buf[32], *ep; @@ -172,15 +172,42 @@ io_nextid(char *iolog_dir, char sessid[7]) log_fatal(USE_ERRNO, _("unable to open %s"), pathbuf); lock_file(fd, SUDO_LOCK); - /* Read seq number (base 36). */ - nread = read(fd, buf, sizeof(buf)); - if (nread != 0) { - if (nread == -1) - log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf); - id = strtoul(buf, &ep, 36); - if (buf == ep || id >= SESSID_MAX) - log_fatal(0, _("invalid sequence number %s"), pathbuf); + /* + * If there is no seq file in iolog_dir and a fallback dir was + * specified, look for seq in the fallback dir. This is to work + * around a bug in sudo 1.8.5 and older where iolog_dir was not + * expanded before the sequence number was updated. + */ + if (iolog_dir_fallback != NULL && fstat(fd, &sb) == 0 && sb.st_size == 0) { + char fallback[PATH_MAX]; + + len = snprintf(fallback, sizeof(fallback), "%s/seq", + iolog_dir_fallback); + if (len > 0 && len < sizeof(fallback)) { + int fd2 = open(fallback, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd2 != -1) { + nread = read(fd2, buf, sizeof(buf)); + if (nread > 0) { + id = strtoul(buf, &ep, 36); + if (buf == ep || id >= SESSID_MAX) + id = 0; + } + close(fd2); + } + } } + + /* Read current seq number (base 36). */ + if (id == 0) { + nread = read(fd, buf, sizeof(buf)); + if (nread != 0) { + if (nread == -1) + log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf); + id = strtoul(buf, &ep, 36); + if (buf == ep || id >= SESSID_MAX) + log_fatal(0, _("invalid sequence number %s"), pathbuf); + } + } id++; /* @@ -198,7 +225,7 @@ io_nextid(char *iolog_dir, char sessid[7]) sessid[6] = '\0'; /* Rewind and overwrite old seq file. */ - if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) log_fatal(USE_ERRNO, _("unable to write to %s"), pathbuf); close(fd); @@ -476,7 +503,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conv /* Get next session ID and convert it into a path. */ tofree = emalloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2); memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR)); - io_nextid(tofree, sessid); + io_nextid(tofree, NULL, sessid); snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2, "%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]); @@ -565,10 +592,10 @@ sudoers_io_open(unsigned int version, sudo_conv_t conv done: efree(tofree); if (details.runas_pw) - pw_delref(details.runas_pw); + sudo_pw_delref(details.runas_pw); sudo_endpwent(); if (details.runas_gr) - gr_delref(details.runas_gr); + sudo_gr_delref(details.runas_gr); sudo_endgrent(); debug_return_bool(rval); @@ -683,7 +710,7 @@ sudoers_io_log_stderr(const char *buf, unsigned int le return sudoers_io_log(buf, len, IOFD_STDERR); } -struct io_plugin sudoers_io = { +__dso_public struct io_plugin sudoers_io = { SUDO_IO_PLUGIN, SUDO_API_VERSION, sudoers_io_open,