Hello -
I was testing some login data collection scripts (on a VM)
and discovered that in certain cases, it was possible for a
login record to not be fully commited to disk prior to
system shutdown, resulting in the last(1) entry for the
login not being visible. (was doing e.g. ssh root@testbox
to generate wtmp login records and then powering off the vm
to see if my code processed unclean shutdown records correctly).
I could see in some scenarios, aside from generating incorrect
data, this incorrect record could be used to facillitate hiding
presence of a successful compromise.
The attached patch calls fsync(2) on related FD's in the login(3)
routines, which corrected the problem on my test machine,
and imho might be a good idea in general.
The patch was generated on 5.8 current, but based on a
rudimentary check of head it looks like it should apply cleanly
and is 3 lines of diff if not :)
It might be useful also to have last(1) warn of truncated/
incomplete records as were the case in my (I think now lost)
corrupt wtmp file.. I did not attempt to implement this.
Please let me know if there are any questions or concerns
and thanks for a great system.
Thanks,
- Chris
Index: lib/libutil/login.c
===================================================================
RCS file: /cvs/src/lib/libutil/login.c,v
retrieving revision 1.10
diff -u -p -r1.10 login.c
--- lib/libutil/login.c 2 Aug 2005 21:46:23 -0000 1.10
+++ lib/libutil/login.c 30 Oct 2015 15:53:04 -0000
@@ -62,10 +62,12 @@ login(struct utmp *utp)
(void)memcpy(utp->ut_host, old_ut.ut_host, UT_HOSTSIZE);
(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
(void)write(fd, utp, sizeof(struct utmp));
+ (void)fsync(fd);
(void)close(fd);
}
if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
(void)write(fd, utp, sizeof(struct utmp));
+ (void)fsync(fd);
(void)close(fd);
}
}
Index: lib/libutil/logout.c
===================================================================
RCS file: /cvs/src/lib/libutil/logout.c,v
retrieving revision 1.8
diff -u -p -r1.8 logout.c
--- lib/libutil/logout.c 2 Aug 2005 21:46:23 -0000 1.8
+++ lib/libutil/logout.c 30 Oct 2015 15:53:34 -0000
@@ -60,6 +60,7 @@ logout(const char *line)
(void)write(fd, &ut, sizeof(UTMP));
rval = 1;
}
+ (void)fsync(fd);
(void)close(fd);
return(rval);
}
Index: lib/libutil/logwtmp.c
===================================================================
RCS file: /cvs/src/lib/libutil/logwtmp.c,v
retrieving revision 1.9
diff -u -p -r1.9 logwtmp.c
--- lib/libutil/logwtmp.c 2 Aug 2005 21:46:23 -0000 1.9
+++ lib/libutil/logwtmp.c 30 Oct 2015 15:46:38 -0000
@@ -57,5 +57,6 @@ logwtmp(const char *line, const char *na
sizeof(struct utmp))
(void) ftruncate(fd, buf.st_size);
}
+ (void) fsync(fd);
(void) close(fd);
}