diff options
author | Mark Johnston <markj@FreeBSD.org> | 2024-04-03 15:29:25 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2024-04-03 15:31:43 +0000 |
commit | 87e63f2e7f92e192c1e8b01ac7cc45b88c03a478 (patch) | |
tree | 2ab7f26339b2ec1aec345db1a103a9c54f406130 /sbin | |
parent | 0238d3711d9b888f678fce4274eccc9175168395 (diff) | |
download | src-87e63f2e7f92e192c1e8b01ac7cc45b88c03a478.tar.gz src-87e63f2e7f92e192c1e8b01ac7cc45b88c03a478.zip |
nextboot: Write nextboot.conf safely
As in the old nextboot.sh script:
- First write everything to a tempfile instead of /boot/nextboot.conf.
- fsync() the tempfile before renaming it to nextboot.conf.
Fixes: fd6d47375a78 ("rescue,nextboot: Install nextboot as a link to reboot, rm nextboot.sh")
Reviewed by: imp
Differential Revision: https://reviews.freebsd.org/D44572
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/reboot/reboot.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c index 3cc77aebe4d4..1b806a90de1d 100644 --- a/sbin/reboot/reboot.c +++ b/sbin/reboot/reboot.c @@ -113,8 +113,10 @@ zfsbootcfg(const char *pool, bool force) static void write_nextboot(const char *fn, const char *env, bool force) { + char tmp[PATH_MAX]; FILE *fp; struct statfs sfs; + int tmpfd; bool supported = false; bool zfs = false; @@ -138,21 +140,39 @@ write_nextboot(const char *fn, const char *env, bool force) zfsbootcfg(sfs.f_mntfromname, force); } - fp = fopen(fn, "w"); + if (strlcpy(tmp, fn, sizeof(tmp)) >= sizeof(tmp)) + E("Path too long %s", fn); + if (strlcat(tmp, ".XXXXXX", sizeof(tmp)) >= sizeof(tmp)) + E("Path too long %s", fn); + tmpfd = mkstemp(tmp); + if (tmpfd == -1) + E("mkstemp %s", tmp); + + fp = fdopen(tmpfd, "w"); if (fp == NULL) - E("Can't create %s", fn); + E("fdopen %s", tmp); - if (fprintf(fp,"%s%s", + if (fprintf(fp, "%s%s", supported ? "nextboot_enable=\"YES\"\n" : "", env != NULL ? env : "") < 0) { int e; e = errno; - fclose(fp); - if (unlink(fn)) - warn("unlink %s", fn); + if (unlink(tmp)) + warn("unlink %s", tmp); + errno = e; + E("Can't write %s", tmp); + } + if (fsync(fileno(fp)) != 0) + E("Can't fsync %s", fn); + if (rename(tmp, fn) != 0) { + int e; + + e = errno; + if (unlink(tmp)) + warn("unlink %s", tmp); errno = e; - E("Can't write %s", fn); + E("Can't rename %s to %s", tmp, fn); } fclose(fp); } @@ -194,8 +214,8 @@ add_env(char **env, const char *key, const char *value) /* * Different options are valid for different programs. */ -#define GETOPT_REBOOT "cDde:k:lNno:pqr" -#define GETOPT_NEXTBOOT "De:k:o:" +#define GETOPT_REBOOT "cDde:fk:lNno:pqr" +#define GETOPT_NEXTBOOT "De:fk:o:" int main(int argc, char *argv[]) |