summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2019-07-08 11:10:31 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2019-07-08 11:10:31 +0000
commit13d098c6d737623ea5038b3e348751b5ebf11fa2 (patch)
treeb18b52251d7e33a05043e754a9d44d0df955dae6
parent34b00c71708ebe67122f1965b9f736f802ce14f2 (diff)
downloadutmps-13d098c6d737623ea5038b3e348751b5ebf11fa2.tar.xz
bugfix: utmps-utmpd locking was too fine-grained.
Also prepare for 0.0.2.2
-rw-r--r--NEWS5
-rw-r--r--doc/index.html2
-rw-r--r--doc/upgrade.html6
-rw-r--r--package/info2
-rw-r--r--src/utmps/utmps-utmpd.c63
5 files changed, 62 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index 469d7fc..6028d09 100644
--- a/NEWS
+++ b/NEWS
@@ -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) ;
}