diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2019-07-08 11:10:31 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2019-07-08 11:10:31 +0000 |
commit | 13d098c6d737623ea5038b3e348751b5ebf11fa2 (patch) | |
tree | b18b52251d7e33a05043e754a9d44d0df955dae6 | |
parent | 34b00c71708ebe67122f1965b9f736f802ce14f2 (diff) | |
download | utmps-13d098c6d737623ea5038b3e348751b5ebf11fa2.tar.xz |
bugfix: utmps-utmpd locking was too fine-grained.
Also prepare for 0.0.2.2
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/upgrade.html | 6 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/utmps/utmps-utmpd.c | 63 |
5 files changed, 62 insertions, 16 deletions
@@ -1,5 +1,10 @@ Changelog for utmps. +In 0.0.2.2 +---------- + + - Bugfixes. + In 0.0.2.1 ---------- diff --git a/doc/index.html b/doc/index.html index c1e5d42..8f5cafe 100644 --- a/doc/index.html +++ b/doc/index.html @@ -76,7 +76,7 @@ suitable replacement for <h3> Download </h3> <ul> - <li> The current released version of utmps is <a href="utmps-0.0.2.1.tar.gz">0.0.2.1</a>. </li> + <li> The current released version of utmps is <a href="utmps-0.0.2.2.tar.gz">0.0.2.2</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/utmps/">utmps git repository</a>: diff --git a/doc/upgrade.html b/doc/upgrade.html index 656e01e..fff70a0 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,6 +18,12 @@ <h1> What has changed in utmps </h1> +<h2> in 0.0.2.2 </h2> + +<ul> + <li> No functional changes. </li> +</ul> + <h2> in 0.0.2.1 </h2> <ul> diff --git a/package/info b/package/info index cd2efe0..901bb53 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=utmps -version=0.0.2.1 +version=0.0.2.2 category=admin package_macro_name=UTMPS diff --git a/src/utmps/utmps-utmpd.c b/src/utmps/utmps-utmpd.c index 69d6b8e..9fa66d3 100644 --- a/src/utmps/utmps-utmpd.c +++ b/src/utmps/utmps-utmpd.c @@ -60,22 +60,34 @@ static void maybe_open (void) } } -static int read_utmp_entry (char *s) +static int read_utmp_entry_unlocked (char *s) { - ssize_t r ; - if (lock_sh(fd) < 0) goto err ; - r = read(fd, s, sizeof(struct utmpx)) ; - lock_unx(fd) ; + ssize_t r = read(fd, s, sizeof(struct utmpx)) ; if (r < 0) goto err ; if (!r) return 0 ; if (r == sizeof(struct utmpx)) return 1 ; errno = EPIPE ; - err: - unlink_void("utmp") ; - answer(errno) ; + err: + unlink_void("utmp") ; + answer(errno) ; strerr_diefu1sys(111, "read utmp file") ; } +static void lockit (int w) +{ + if ((w ? lock_ex(fd) : lock_sh(fd)) < 0) + { + unlink_void("utmp") ; + answer(errno) ; + strerr_diefu1sys(111, "read utmp file") ; + } +} + +static inline void unlockit (void) +{ + lock_unx(fd) ; +} + static int idmatch (unsigned short type, char const *id, struct utmpx const *b) { if (type == BOOT_TIME || type == OLD_TIME || type == NEW_TIME) @@ -95,7 +107,14 @@ static void do_getent (void) struct utmpx b ; char buf[1 + sizeof(struct utmpx)] = "" ; maybe_open() ; - if (!read_utmp_entry(buf+1)) { answer(ESRCH) ; return ; } + lockit(0) ; + if (!read_utmp_entry_unlocked(buf+1)) + { + unlockit() ; + answer(ESRCH) ; + return ; + } + unlockit() ; utmps_utmpx_unpack(buf+1, &b) ; utmps_utmpx_pack(buf+1, &b) ; buffer_putnoflush(buffer_1small, buf, 1 + sizeof(struct utmpx)) ; @@ -111,13 +130,20 @@ static void do_getid (void) ushort_unpack_big(rbuf, &type) ; rbuf[USHORT_PACK + UTMPS_UT_IDSIZE - 1] = 0 ; maybe_open() ; + lockit(0) ; for (;;) { struct utmpx b ; - if (!read_utmp_entry(sbuf+1)) { answer(ESRCH) ; return ; } + if (!read_utmp_entry_unlocked(sbuf+1)) + { + unlockit() ; + answer(ESRCH) ; + return ; + } utmps_utmpx_unpack(sbuf+1, &b) ; if (idmatch(type, rbuf + USHORT_PACK, &b)) break ; } + unlockit() ; buffer_putnoflush(buffer_1small, sbuf, 1 + sizeof(struct utmpx)) ; flush1() ; } @@ -129,14 +155,21 @@ static void do_getline (void) get0(rbuf, UTMPS_UT_LINESIZE) ; rbuf[UTMPS_UT_LINESIZE - 1] = 0 ; maybe_open() ; + lockit(0) ; for (;;) { struct utmpx b ; - if (!read_utmp_entry(sbuf+1)) { answer(ESRCH) ; return ; } + if (!read_utmp_entry_unlocked(sbuf+1)) + { + unlockit() ; + answer(ESRCH) ; + return ; + } utmps_utmpx_unpack(sbuf+1, &b) ; if ((b.ut_type == LOGIN_PROCESS || b.ut_type == USER_PROCESS) && !strncmp(rbuf, b.ut_line, UTMPS_UT_LINESIZE - 1)) break ; } + unlockit() ; buffer_putnoflush(buffer_1small, sbuf, 1 + sizeof(struct utmpx)) ; flush1() ; } @@ -153,16 +186,18 @@ static void do_putline (uid_t uid, gid_t gid) } utmps_utmpx_unpack(buf, &u) ; maybe_open() ; + lockit(1) ; for (;;) { struct utmpx b ; char tmp[sizeof(struct utmpx)] ; - if (!read_utmp_entry(tmp)) break ; + if (!read_utmp_entry_unlocked(tmp)) break ; utmps_utmpx_unpack(tmp, &b) ; if (idmatch(u.ut_type, u.ut_id, &b) && !strncmp(u.ut_line, b.ut_line, UTMPS_UT_LINESIZE - 1)) { if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_CUR) < 0) { + unlockit() ; answer(errno) ; return ; } @@ -170,14 +205,14 @@ static void do_putline (uid_t uid, gid_t gid) } } utmps_utmpx_pack(buf, &u) ; - if (lock_ex(fd) < 0) { answer(errno) ; return ; } if (allwrite(fd, buf, sizeof(struct utmpx)) < sizeof(struct utmpx)) { + unlockit() ; answer(errno) ; strerr_diefu1sys(111, "write to utmp") ; } fsync(fd) ; - lock_unx(fd) ; + unlockit() ; answer(0) ; } |