Use pread(2) and pwrite(2) where possible.

This commit is contained in:
Todd C. Miller
2015-09-07 06:06:08 -06:00
parent 70914b3328
commit 7d0a623fdd
5 changed files with 50 additions and 22 deletions

View File

@@ -525,6 +525,9 @@
/* Define to 1 if you have the `posix_spawnp' function. */ /* Define to 1 if you have the `posix_spawnp' function. */
#undef HAVE_POSIX_SPAWNP #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. */ /* Define to 1 if you have the `priv_set' function. */
#undef HAVE_PRIV_SET #undef HAVE_PRIV_SET
@@ -540,6 +543,9 @@
/* Define to 1 if you have the <pty.h> header file. */ /* Define to 1 if you have the <pty.h> header file. */
#undef HAVE_PTY_H #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. */ /* Define to 1 if you have the `pw_dup' function. */
#undef HAVE_PW_DUP #undef HAVE_PW_DUP

6
configure vendored
View File

@@ -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 " killpg"
as_fn_append ac_func_list " nl_langinfo" as_fn_append ac_func_list " nl_langinfo"
as_fn_append ac_func_list " strftime" 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" as_fn_append ac_func_list " seteuid"
# Check that the precious variables saved in the cache have kept the same # Check that the precious variables saved in the cache have kept the same
# value. # value.
@@ -18084,6 +18086,10 @@ done
for ac_func in getgrouplist for ac_func in getgrouplist
do : do :
ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist" ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist"

View File

@@ -2389,7 +2389,7 @@ dnl
dnl Function checks dnl Function checks
dnl dnl
AC_FUNC_GETGROUPS 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], [], [ AC_CHECK_FUNCS([getgrouplist], [], [
case "$host_os" in case "$host_os" in
aix*) aix*)

View File

@@ -269,7 +269,11 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
sessid[6] = '\0'; sessid[6] = '\0';
/* Rewind and overwrite old seq file, including the NUL byte. */ /* 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); log_warning(SLOG_SEND_MAIL, N_("unable to write to %s"), pathbuf);
debug_return_bool(false); debug_return_bool(false);
} }

View File

@@ -61,8 +61,6 @@
* The TS_LOCKEXCL entry must be unlocked before locking the actual record. * The TS_LOCKEXCL entry must be unlocked before locking the actual record.
*/ */
/* TODO: use pread/pwrite when possible */
struct ts_cookie { struct ts_cookie {
char *fname; char *fname;
int fd; int fd;
@@ -274,14 +272,29 @@ ts_open(const char *path, int flags)
} }
static ssize_t 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; ssize_t nwritten;
off_t old_eof; off_t old_eof;
debug_decl(ts_write, SUDOERS_DEBUG_AUTH) debug_decl(ts_write, SUDOERS_DEBUG_AUTH)
old_eof = lseek(fd, (off_t)0, SEEK_CUR); if (offset == -1) {
nwritten = write(fd, entry, entry->size); 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 ((size_t)nwritten != entry->size) {
if (nwritten == -1) { if (nwritten == -1) {
log_warning(SLOG_SEND_MAIL, 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. */ /* 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) { if (lseek(cookie->fd, cookie->pos, SEEK_SET) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"unable to seek to %lld", (long long)cookie->pos); "unable to seek to %lld", (long long)cookie->pos);
goto done; goto done;
} }
nread = read(cookie->fd, entry, sizeof(*entry)); nread = read(cookie->fd, entry, sizeof(*entry));
#endif
if (nread != sizeof(*entry)) { if (nread != sizeof(*entry)) {
/* short read, should not happen */ /* short read, should not happen */
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, 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.version = TS_VERSION;
entry.size = sizeof(entry); entry.size = sizeof(entry);
entry.type = TS_LOCKEXCL; 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); debug_return_bool(false);
} else if (entry.type != TS_LOCKEXCL) { } else if (entry.type != TS_LOCKEXCL) {
/* Old sudo record, convert it to TS_LOCKEXCL. */ /* Old sudo record, convert it to TS_LOCKEXCL. */
entry.type = TS_LOCKEXCL; entry.type = TS_LOCKEXCL;
memset((char *)&entry + offsetof(struct timestamp_entry, type), 0, memset((char *)&entry + offsetof(struct timestamp_entry, type), 0,
nread - offsetof(struct timestamp_entry, type)); 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); debug_return_bool(false);
} }
@@ -582,7 +599,7 @@ timestamp_lock(void *vcookie, struct passwd *pw)
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"appending new tty time stamp record"); "appending new tty time stamp record");
lock_pos = lseek(cookie->fd, 0, SEEK_CUR); 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); debug_return_bool(false);
} }
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, 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; cookie->pos = lseek(cookie->fd, 0, SEEK_CUR) - (off_t)entry.size;
} else { } else {
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, 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); 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); debug_return_bool(false);
} }
} }
@@ -724,7 +741,7 @@ timestamp_status(void *vcookie, struct passwd *pw)
N_("ignoring time stamp from the future")); N_("ignoring time stamp from the future"));
status = TS_OLD; status = TS_OLD;
SET(entry.flags, TS_DISABLED); SET(entry.flags, TS_DISABLED);
ts_write(cookie->fd, cookie->fname, &entry); ts_write(cookie->fd, cookie->fname, &entry, cookie->pos);
} }
#else #else
/* Check for bogus (future) time in the stampfile. */ /* Check for bogus (future) time in the stampfile. */
@@ -737,7 +754,7 @@ timestamp_status(void *vcookie, struct passwd *pw)
4 + ctime(&tv_sec)); 4 + ctime(&tv_sec));
status = TS_OLD; status = TS_OLD;
SET(entry.flags, TS_DISABLED); SET(entry.flags, TS_DISABLED);
ts_write(cookie->fd, cookie->fname, &entry); ts_write(cookie->fd, cookie->fname, &entry, cookie->pos);
} }
#endif /* CLOCK_MONOTONIC */ #endif /* CLOCK_MONOTONIC */
} else { } else {
@@ -779,15 +796,10 @@ timestamp_update(void *vcookie, struct passwd *pw)
} }
/* Write out the locked record. */ /* 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, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"writing %zu byte record at %lld", sizeof(cookie->key), "writing %zu byte record at %lld", sizeof(cookie->key),
(long long)cookie->pos); (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; rval = true;
done: done:
@@ -845,9 +857,9 @@ timestamp_remove(bool unlink_it)
while (ts_find_record(fd, &key, &entry)) { while (ts_find_record(fd, &key, &entry)) {
/* Back up and disable the entry. */ /* Back up and disable the entry. */
if (!ISSET(entry.flags, TS_DISABLED)) { if (!ISSET(entry.flags, TS_DISABLED)) {
lseek(fd, (off_t)0 - sizeof(entry), SEEK_CUR);
SET(entry.flags, TS_DISABLED); 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; rval = false;
} }
} }