--- b/lib/libc/gen/pututxline.c +++ b/lib/libc/gen/pututxline.c @@ -43,26 +43,40 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" static FILE * -futx_open(const char *file) +futx_open(const char *file, const char *lkfile, int *lkfd_out) { FILE *fp; struct stat sb; - int fd; + int fd, lkfd, serrno; + + fd = -1; + fp = NULL; + serrno = 0; + + lkfd = _open(lkfile, O_CREAT|O_RDWR|O_EXLOCK|O_CLOEXEC, 0600); + if (lkfd < 0) + return (NULL); fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK|O_CLOEXEC, 0644); if (fd < 0) - return (NULL); + goto out; /* Safety check: never use broken files. */ if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0) { - _close(fd); - errno = EFTYPE; - return (NULL); + serrno = EFTYPE; + goto out; } fp = fdopen(fd, "r+"); + *lkfd_out = lkfd; +out: if (fp == NULL) { - _close(fd); + if (fd >= 0) + _close(fd); + if (lkfd >= 0) + _close(lkfd); + if (serrno != 0) + errno = serrno; return (NULL); } return (fp); @@ -74,7 +88,7 @@ utx_active_add(const struct futx *fu) FILE *fp; struct futx fe; off_t partial; - int error, ret; + int error, ret, lkfd; partial = -1; ret = 0; @@ -83,7 +97,7 @@ utx_active_add(const struct futx *fu) * Register user login sessions. Overwrite entries of sessions * that have already been terminated. */ - fp = futx_open(_PATH_UTX_ACTIVE); + fp = futx_open(_PATH_UTX_ACTIVE, _PATH_UTX_ACTIVE_LK, &lkfd); if (fp == NULL) return (-1); while (fread(&fe, sizeof(fe), 1, fp) == 1) { @@ -133,6 +147,7 @@ utx_active_add(const struct futx *fu) else error = 0; fclose(fp); + _close(lkfd); if (error != 0) errno = error; return (error == 0 ? 0 : 1); @@ -143,12 +158,12 @@ utx_active_remove(struct futx *fu) { FILE *fp; struct futx fe; - int error, ret; + int error, ret, lkfd; /* * Remove user login sessions, having the same ut_id. */ - fp = futx_open(_PATH_UTX_ACTIVE); + fp = futx_open(_PATH_UTX_ACTIVE, _PATH_UTX_ACTIVE_LK, &lkfd); if (fp == NULL) return (-1); error = ESRCH; @@ -172,6 +187,7 @@ utx_active_remove(struct futx *fu) } fclose(fp); + _close(lkfd); if (ret != 0) errno = error; return (ret); @@ -202,7 +218,7 @@ utx_lastlogin_add(const struct futx *fu) { struct futx fe; FILE *fp; - int error, ret; + int error, ret, lkfd; ret = 0; @@ -211,7 +227,7 @@ utx_lastlogin_add(const struct futx *fu) * current user already has an entry. If not, append a new * entry. */ - fp = futx_open(_PATH_UTX_LASTLOGIN); + fp = futx_open(_PATH_UTX_LASTLOGIN, _PATH_UTX_LASTLOGIN_LK, &lkfd); if (fp == NULL) return (-1); while (fread(&fe, sizeof fe, 1, fp) == 1) { @@ -229,6 +245,7 @@ utx_lastlogin_add(const struct futx *fu) ret = -1; } fclose(fp); + _close(lkfd); if (ret == -1) errno = error; return (ret); --- b/lib/libc/gen/utxdb.h +++ b/lib/libc/gen/utxdb.h @@ -34,8 +34,11 @@ #include #define _PATH_UTX_ACTIVE "/var/run/utx.active" +#define _PATH_UTX_ACTIVE_LK "/var/run/.utx.active.lock" #define _PATH_UTX_LASTLOGIN "/var/log/utx.lastlogin" +#define _PATH_UTX_LASTLOGIN_LK "/var/log/.utx.lastlogin.lock" #define _PATH_UTX_LOG "/var/log/utx.log" +#define _PATH_UTX_LOG_LK "/var/log/.utx.log.lock" /* * Entries in struct futx are ordered by how often they are used. In