summaryrefslogtreecommitdiff
path: root/util/nvmutil/lib/io.c
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-20 04:02:51 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-22 13:50:44 +0000
commit6838db4647b600bf5b356429f54850bf801e7ba4 (patch)
treecc98541897703d2949af27dc050cad8cba5061a0 /util/nvmutil/lib/io.c
parentf50ffd6bb13c04cb185fb6311f8875582bf18388 (diff)
WIP: hardened mktemp
i'm pretty much nearly there. still no dir support, only files. i won't keep amending now - will do more, then squash later. Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil/lib/io.c')
-rw-r--r--util/nvmutil/lib/io.c131
1 files changed, 77 insertions, 54 deletions
diff --git a/util/nvmutil/lib/io.c b/util/nvmutil/lib/io.c
index 5769dd05..87163359 100644
--- a/util/nvmutil/lib/io.c
+++ b/util/nvmutil/lib/io.c
@@ -21,7 +21,7 @@
void
open_gbe_file(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct commands *cmd = &x->cmd[x->i];
struct xfile *f = &x->f;
@@ -29,12 +29,12 @@ open_gbe_file(void)
xopen(&f->gbe_fd, f->fname,
cmd->flags | O_BINARY |
- O_NOFOLLOW | O_CLOEXEC, &f->gbe_st);
+ O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, &f->gbe_st);
if (f->gbe_st.st_nlink > 1)
err(EINVAL,
"%s: warning: file has multiple (%lu) hard links\n",
- f->fname, (unsigned long)f->gbe_st.st_nlink);
+ f->fname, (size_t)f->gbe_st.st_nlink);
if (f->gbe_st.st_nlink == 0)
err(EIO, "%s: file unlinked while open", f->fname);
@@ -69,7 +69,7 @@ open_gbe_file(void)
void
copy_gbe(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
read_file();
@@ -77,19 +77,19 @@ copy_gbe(void)
if (f->gbe_file_size == SIZE_8KB)
return;
- memcpy(f->buf + (unsigned long)GBE_PART_SIZE,
- f->buf + (unsigned long)(f->gbe_file_size >> 1),
- (unsigned long)GBE_PART_SIZE);
+ memcpy(f->buf + (size_t)GBE_PART_SIZE,
+ f->buf + (size_t)(f->gbe_file_size >> 1),
+ (size_t)GBE_PART_SIZE);
}
void
read_file(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
struct stat _st;
- long _r;
+ ssize_t _r;
/* read main file
*/
@@ -141,11 +141,11 @@ read_file(void)
void
write_gbe_file(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct commands *cmd = &x->cmd[x->i];
struct xfile *f = &x->f;
- unsigned long p;
+ size_t p;
unsigned char update_checksum;
if ((cmd->flags & O_ACCMODE) == O_RDONLY)
@@ -171,25 +171,25 @@ write_gbe_file(void)
}
void
-rw_gbe_file_part(unsigned long p, int rw_type,
+rw_gbe_file_part(size_t p, int rw_type,
const char *rw_type_str)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct commands *cmd = &x->cmd[x->i];
struct xfile *f = &x->f;
- long rval;
+ ssize_t rval;
off_t file_offset;
- unsigned long gbe_rw_size;
+ size_t gbe_rw_size;
unsigned char *mem_offset;
gbe_rw_size = cmd->rw_size;
if (rw_type < IO_PREAD || rw_type > IO_PWRITE)
err(errno, "%s: %s: part %lu: invalid rw_type, %d",
- f->fname, rw_type_str, (unsigned long)p, rw_type);
+ f->fname, rw_type_str, (size_t)p, rw_type);
mem_offset = gbe_mem_offset(p, rw_type_str);
file_offset = (off_t)gbe_file_offset(p, rw_type_str);
@@ -199,17 +199,17 @@ rw_gbe_file_part(unsigned long p, int rw_type,
if (rval == -1)
err(errno, "%s: %s: part %lu",
- f->fname, rw_type_str, (unsigned long)p);
+ f->fname, rw_type_str, (size_t)p);
- if ((unsigned long)rval != gbe_rw_size)
+ if ((size_t)rval != gbe_rw_size)
err(EIO, "%s: partial %s: part %lu",
- f->fname, rw_type_str, (unsigned long)p);
+ f->fname, rw_type_str, (size_t)p);
}
void
write_to_gbe_bin(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct commands *cmd = &x->cmd[x->i];
struct xfile *f = &x->f;
@@ -240,14 +240,20 @@ write_to_gbe_bin(void)
saved_errno = errno;
if (close_on_eintr(f->tmp_fd) == -1) {
+ f->tmp_fd = -1;
+
fprintf(stderr, "FAIL: %s: close\n", f->tname);
f->io_err_gbe_bin = 1;
}
+ f->tmp_fd = -1;
if (close_on_eintr(f->gbe_fd) == -1) {
+ f->gbe_fd = -1;
+
fprintf(stderr, "FAIL: %s: close\n", f->fname);
f->io_err_gbe_bin = 1;
}
+ f->gbe_fd = -1;
errno = saved_errno;
@@ -274,8 +280,10 @@ write_to_gbe_bin(void)
/* removed by rename
*/
- if (f->tname != NULL)
+ if (f->tname != NULL) {
free(f->tname);
+ f->tname = NULL;
+ }
f->tname = NULL;
}
@@ -292,15 +300,15 @@ write_to_gbe_bin(void)
}
void
-check_written_part(unsigned long p)
+check_written_part(size_t p)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct commands *cmd = &x->cmd[x->i];
struct xfile *f = &x->f;
- long rval;
+ ssize_t rval;
- unsigned long gbe_rw_size;
+ size_t gbe_rw_size;
off_t file_offset;
unsigned char *mem_offset;
@@ -328,7 +336,7 @@ check_written_part(unsigned long p)
if (rval == -1)
f->rw_check_err_read[p] = f->io_err_gbe = 1;
- else if ((unsigned long)rval != gbe_rw_size)
+ else if ((size_t)rval != gbe_rw_size)
f->rw_check_partial_read[p] = f->io_err_gbe = 1;
else if (memcmp(mem_offset, f->pad, gbe_rw_size) != 0)
f->rw_check_bad_part[p] = f->io_err_gbe = 1;
@@ -359,10 +367,10 @@ check_written_part(unsigned long p)
void
report_io_err_rw(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
- unsigned long p;
+ size_t p;
if (!f->io_err_gbe)
return;
@@ -374,22 +382,22 @@ report_io_err_rw(void)
if (f->rw_check_err_read[p])
fprintf(stderr,
"%s: pread: p%lu (post-verification)\n",
- f->fname, (unsigned long)p);
+ f->fname, (size_t)p);
if (f->rw_check_partial_read[p])
fprintf(stderr,
"%s: partial pread: p%lu (post-verification)\n",
- f->fname, (unsigned long)p);
+ f->fname, (size_t)p);
if (f->rw_check_bad_part[p])
fprintf(stderr,
"%s: pwrite: corrupt write on p%lu\n",
- f->fname, (unsigned long)p);
+ f->fname, (size_t)p);
if (f->rw_check_err_read[p] ||
f->rw_check_partial_read[p]) {
fprintf(stderr,
"%s: p%lu: skipped checksum verification "
"(because read failed)\n",
- f->fname, (unsigned long)p);
+ f->fname, (size_t)p);
continue;
}
@@ -402,7 +410,7 @@ report_io_err_rw(void)
fprintf(stderr, "BAD");
fprintf(stderr, " checksum in p%lu on-disk.\n",
- (unsigned long)p);
+ (size_t)p);
if (f->post_rw_checksum[p]) {
fprintf(stderr,
@@ -415,7 +423,7 @@ report_io_err_rw(void)
int
gbe_mv(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
int rval;
@@ -490,8 +498,11 @@ gbe_mv(void)
if (fsync_on_eintr(dest_fd) == -1)
goto ret_gbe_mv;
- if (close_on_eintr(dest_fd) == -1)
+ if (close_on_eintr(dest_fd) == -1) {
+ dest_fd = -1;
goto ret_gbe_mv;
+ }
+ dest_fd = -1;
if (rename(dest_tmp, f->fname) == -1)
goto ret_gbe_mv;
@@ -501,25 +512,37 @@ gbe_mv(void)
goto ret_gbe_mv;
}
- free(dest_tmp);
+ if (dest_tmp != NULL) {
+ free(dest_tmp);
+ dest_tmp = NULL;
+ }
+
dest_tmp = NULL;
ret_gbe_mv:
+ /* TODO: this whole section is bloat.
+ it can be generalised
+ */
+
if (f->gbe_fd > -1) {
- if (close_on_eintr(f->gbe_fd) < 0)
+ if (close_on_eintr(f->gbe_fd) < 0) {
+ f->gbe_fd = -1;
rval = -1;
+ }
+ f->gbe_fd = -1;
+
if (fsync_dir(f->fname) < 0) {
f->io_err_gbe_bin = 1;
rval = -1;
}
- f->gbe_fd = -1;
}
if (f->tmp_fd > -1) {
- if (close_on_eintr(f->tmp_fd) < 0)
+ if (close_on_eintr(f->tmp_fd) < 0) {
+ f->tmp_fd = -1;
rval = -1;
-
+ }
f->tmp_fd = -1;
}
@@ -552,9 +575,9 @@ ret_gbe_mv:
* and it is *also* used during file I/O.
*/
unsigned char *
-gbe_mem_offset(unsigned long p, const char *f_op)
+gbe_mem_offset(size_t p, const char *f_op)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
off_t gbe_off;
@@ -563,7 +586,7 @@ gbe_mem_offset(unsigned long p, const char *f_op)
GBE_PART_SIZE, GBE_WORK_SIZE);
return (unsigned char *)
- (f->buf + (unsigned long)gbe_off);
+ (f->buf + (size_t)gbe_off);
}
/* I/O operations filtered here. These operations must
@@ -571,9 +594,9 @@ gbe_mem_offset(unsigned long p, const char *f_op)
* within the GbE file, and write 4KB of data.
*/
off_t
-gbe_file_offset(unsigned long p, const char *f_op)
+gbe_file_offset(size_t p, const char *f_op)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
off_t gbe_file_half_size;
@@ -585,10 +608,10 @@ gbe_file_offset(unsigned long p, const char *f_op)
}
off_t
-gbe_x_offset(unsigned long p, const char *f_op, const char *d_type,
+gbe_x_offset(size_t p, const char *f_op, const char *d_type,
off_t nsize, off_t ncmp)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
off_t off;
@@ -608,14 +631,14 @@ gbe_x_offset(unsigned long p, const char *f_op, const char *d_type,
return off;
}
-long
-rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw,
+ssize_t
+rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw,
off_t off, int rw_type)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f = &x->f;
- long r;
+ ssize_t r;
if (io_args(fd, mem, nrw, off, rw_type) == -1)
return -1;
@@ -624,17 +647,17 @@ rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw,
if (mem < f->buf)
goto err_rw_gbe_file_exact;
- if ((unsigned long)(mem - f->buf) >= GBE_WORK_SIZE)
+ if ((size_t)(mem - f->buf) >= GBE_WORK_SIZE)
goto err_rw_gbe_file_exact;
}
if (off < 0 || off >= f->gbe_file_size)
goto err_rw_gbe_file_exact;
- if (nrw > (unsigned long)(f->gbe_file_size - off))
+ if (nrw > (size_t)(f->gbe_file_size - off))
goto err_rw_gbe_file_exact;
- if (nrw > (unsigned long)GBE_PART_SIZE)
+ if (nrw > (size_t)GBE_PART_SIZE)
goto err_rw_gbe_file_exact;
r = rw_file_exact(fd, mem, nrw, off, rw_type,