From 7d0a623fdd628849e6b102da3fd9f76a46e4ad2e Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 7 Sep 2015 06:06:08 -0600 Subject: [PATCH] Use pread(2) and pwrite(2) where possible. --- config.h.in | 6 +++++ configure | 6 +++++ configure.ac | 2 +- plugins/sudoers/iolog.c | 6 ++++- plugins/sudoers/timestamp.c | 52 +++++++++++++++++++++++-------------- 5 files changed, 50 insertions(+), 22 deletions(-) diff --git a/config.h.in b/config.h.in index 85ecf5db7..2635a0ffc 100644 --- a/config.h.in +++ b/config.h.in @@ -525,6 +525,9 @@ /* Define to 1 if you have the `posix_spawnp' function. */ #undef HAVE_POSIX_SPAWNP +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + /* Define to 1 if you have the `priv_set' function. */ #undef HAVE_PRIV_SET @@ -540,6 +543,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_PTY_H +/* Define to 1 if you have the `pwrite' function. */ +#undef HAVE_PWRITE + /* Define to 1 if you have the `pw_dup' function. */ #undef HAVE_PW_DUP diff --git a/configure b/configure index a600d7c1a..147df4317 100755 --- a/configure +++ b/configure @@ -2653,6 +2653,8 @@ as_fn_append ac_header_list " sys/sysmacros.h" as_fn_append ac_func_list " killpg" as_fn_append ac_func_list " nl_langinfo" as_fn_append ac_func_list " strftime" +as_fn_append ac_func_list " pread" +as_fn_append ac_func_list " pwrite" as_fn_append ac_func_list " seteuid" # Check that the precious variables saved in the cache have kept the same # value. @@ -18084,6 +18086,10 @@ done + + + + for ac_func in getgrouplist do : ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist" diff --git a/configure.ac b/configure.ac index a997e9130..a287d948a 100644 --- a/configure.ac +++ b/configure.ac @@ -2389,7 +2389,7 @@ dnl dnl Function checks dnl AC_FUNC_GETGROUPS -AC_CHECK_FUNCS_ONCE([killpg nl_langinfo strftime]) +AC_CHECK_FUNCS_ONCE([killpg nl_langinfo strftime pread pwrite]) AC_CHECK_FUNCS([getgrouplist], [], [ case "$host_os" in aix*) diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 9a4f97c78..c7b4584cd 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -269,7 +269,11 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]) sessid[6] = '\0'; /* Rewind and overwrite old seq file, including the NUL byte. */ - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) { +#ifdef HAVE_PWRITE + if (pwrite(fd, buf, 7, 0) != 7) { +#else + if (lseek(fd, 0, SEEK_SET) == -1 || write(fd, buf, 7) != 7) { +#endif log_warning(SLOG_SEND_MAIL, N_("unable to write to %s"), pathbuf); debug_return_bool(false); } diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index 307f03321..5f838cab0 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -61,8 +61,6 @@ * The TS_LOCKEXCL entry must be unlocked before locking the actual record. */ -/* TODO: use pread/pwrite when possible */ - struct ts_cookie { char *fname; int fd; @@ -274,14 +272,29 @@ ts_open(const char *path, int flags) } static ssize_t -ts_write(int fd, const char *fname, struct timestamp_entry *entry) +ts_write(int fd, const char *fname, struct timestamp_entry *entry, off_t offset) { ssize_t nwritten; off_t old_eof; debug_decl(ts_write, SUDOERS_DEBUG_AUTH) - old_eof = lseek(fd, (off_t)0, SEEK_CUR); - nwritten = write(fd, entry, entry->size); + if (offset == -1) { + old_eof = lseek(fd, 0, SEEK_CUR); + nwritten = write(fd, entry, entry->size); + } else { + old_eof = offset; +#ifdef HAVE_PWRITE + nwritten = pwrite(fd, entry, entry->size, offset); +#else + if (lseek(fd, offset, SEEK_SET) == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, + "unable to seek to %lld", offset); + nwritten = -1; + } else { + nwritten = write(fd, entry, entry->size); + } +#endif + } if ((size_t)nwritten != entry->size) { if (nwritten == -1) { log_warning(SLOG_SEND_MAIL, @@ -500,12 +513,16 @@ ts_read(struct ts_cookie *cookie, struct timestamp_entry *entry) } /* Seek to the record position and read it. */ +#ifdef HAVE_PREAD + nread = pread(cookie->fd, entry, sizeof(*entry), cookie->pos); +#else if (lseek(cookie->fd, cookie->pos, SEEK_SET) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, "unable to seek to %lld", (long long)cookie->pos); goto done; } nread = read(cookie->fd, entry, sizeof(*entry)); +#endif if (nread != sizeof(*entry)) { /* short read, should not happen */ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, @@ -559,14 +576,14 @@ timestamp_lock(void *vcookie, struct passwd *pw) entry.version = TS_VERSION; entry.size = sizeof(entry); entry.type = TS_LOCKEXCL; - if (ts_write(cookie->fd, cookie->fname, &entry) == -1) + if (ts_write(cookie->fd, cookie->fname, &entry, -1) == -1) debug_return_bool(false); } else if (entry.type != TS_LOCKEXCL) { /* Old sudo record, convert it to TS_LOCKEXCL. */ entry.type = TS_LOCKEXCL; memset((char *)&entry + offsetof(struct timestamp_entry, type), 0, nread - offsetof(struct timestamp_entry, type)); - if (ts_write(cookie->fd, cookie->fname, &entry) == -1) + if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1) debug_return_bool(false); } @@ -582,7 +599,7 @@ timestamp_lock(void *vcookie, struct passwd *pw) sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "appending new tty time stamp record"); lock_pos = lseek(cookie->fd, 0, SEEK_CUR); - if (ts_write(cookie->fd, cookie->fname, &cookie->key) == -1) + if (ts_write(cookie->fd, cookie->fname, &cookie->key, -1) == -1) debug_return_bool(false); } sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, @@ -607,9 +624,9 @@ timestamp_lock(void *vcookie, struct passwd *pw) cookie->pos = lseek(cookie->fd, 0, SEEK_CUR) - (off_t)entry.size; } else { sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "appending new globbal record"); + "appending new global record"); cookie->pos = lseek(cookie->fd, 0, SEEK_CUR); - if (ts_write(cookie->fd, cookie->fname, &cookie->key) == -1) + if (ts_write(cookie->fd, cookie->fname, &cookie->key, -1) == -1) debug_return_bool(false); } } @@ -724,7 +741,7 @@ timestamp_status(void *vcookie, struct passwd *pw) N_("ignoring time stamp from the future")); status = TS_OLD; SET(entry.flags, TS_DISABLED); - ts_write(cookie->fd, cookie->fname, &entry); + ts_write(cookie->fd, cookie->fname, &entry, cookie->pos); } #else /* Check for bogus (future) time in the stampfile. */ @@ -737,7 +754,7 @@ timestamp_status(void *vcookie, struct passwd *pw) 4 + ctime(&tv_sec)); status = TS_OLD; SET(entry.flags, TS_DISABLED); - ts_write(cookie->fd, cookie->fname, &entry); + ts_write(cookie->fd, cookie->fname, &entry, cookie->pos); } #endif /* CLOCK_MONOTONIC */ } else { @@ -779,15 +796,10 @@ timestamp_update(void *vcookie, struct passwd *pw) } /* Write out the locked record. */ - if (lseek(cookie->fd, cookie->pos, SEEK_SET) == -1) { - sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, - "unable to seek to %lld", (long long)cookie->pos); - goto done; - } sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "writing %zu byte record at %lld", sizeof(cookie->key), (long long)cookie->pos); - if (ts_write(cookie->fd, cookie->fname, &cookie->key) != -1) + if (ts_write(cookie->fd, cookie->fname, &cookie->key, cookie->pos) != -1) rval = true; done: @@ -845,9 +857,9 @@ timestamp_remove(bool unlink_it) while (ts_find_record(fd, &key, &entry)) { /* Back up and disable the entry. */ if (!ISSET(entry.flags, TS_DISABLED)) { - lseek(fd, (off_t)0 - sizeof(entry), SEEK_CUR); SET(entry.flags, TS_DISABLED); - if (ts_write(fd, fname, &entry) == -1) + lseek(fd, 0 - sizeof(entry), SEEK_CUR); + if (ts_write(fd, fname, &entry, -1) == -1) rval = false; } } -- 2.50.1