summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib/file.c')
-rw-r--r--util/libreboot-utils/lib/file.c83
1 files changed, 35 insertions, 48 deletions
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c
index 5d656e0e..3620f425 100644
--- a/util/libreboot-utils/lib/file.c
+++ b/util/libreboot-utils/lib/file.c
@@ -62,27 +62,7 @@ same_file(int fd, struct stat *st_old,
return 0;
err_same_file:
-
- if (errno == saved_errno)
- errno = ESTALE;
-
- return -1;
-}
-
-void
-xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
-{
- if ((*fd_ptr = open(path, flags)) < 0)
- err_exit(errno, "%s", path);
-
- if (fstat(*fd_ptr, st) < 0)
- err_exit(errno, "%s: stat", path);
-
- if (!S_ISREG(st->st_mode))
- err_exit(errno, "%s: not a regular file", path);
-
- if (lseek_on_eintr(*fd_ptr, 0, SEEK_CUR, 1, 1) == (off_t)-1)
- err_exit(errno, "%s: file not seekable", path);
+ return set_errno(saved_errno, ESTALE);
}
int
@@ -155,13 +135,11 @@ fsync_dir(const char *path)
err_fsync_dir:
- if (errno == saved_errno)
- errno = EIO;
free_and_set_null(&dirbuf);
close_on_eintr(&dirfd);
- return -1;
+ return set_errno(saved_errno, EIO);
}
/* rw_file_exact() - Read perfectly or die
@@ -264,10 +242,7 @@ rw_file_exact(int fd, unsigned char *mem, size_t nrw,
err_rw_file_exact:
- if (errno == saved_errno)
- errno = EIO;
-
- return -1;
+ return set_errno(saved_errno, EIO);
}
/* prw() - portable read-write with more
@@ -446,11 +421,7 @@ real_pread_pwrite:
#endif
err_prw:
-
- if (errno == saved_errno)
- errno = EIO;
-
- return -1;
+ return set_errno(saved_errno, EIO);
}
int
@@ -472,10 +443,7 @@ io_args(int fd, void *mem, size_t nrw,
return 0;
err_io_args:
- if (errno == saved_errno)
- errno = EINVAL;
-
- return -1;
+ return set_errno(saved_errno, EINVAL);
}
int
@@ -493,10 +461,7 @@ check_file(int fd, struct stat *st)
return 0;
err_is_file:
- if (errno == saved_errno)
- errno = EINVAL;
-
- return -1;
+ return set_errno(saved_errno, EINVAL);
}
/* POSIX can say whatever it wants.
@@ -518,10 +483,7 @@ rw_over_nrw(ssize_t r, size_t nrw)
return r;
err_rw_over_nrw:
- if (errno == saved_errno)
- errno = EIO;
-
- return -1;
+ return set_errno(saved_errno, EIO);
}
off_t
@@ -590,8 +552,9 @@ free_and_set_null(char **buf)
}
void
-open_on_eintr(char *path,
- int *fd, int flags, mode_t mode)
+open_on_eintr(const char *path,
+ int *fd, int flags, mode_t mode,
+ struct stat *st)
{
int r = -1;
int saved_errno = errno;
@@ -616,6 +579,17 @@ open_on_eintr(char *path,
*fd = r;
+ if (st != NULL) {
+ if (fstat(*fd, st) < 0)
+ err_exit(errno, "%s: stat", path);
+
+ if (!S_ISREG(st->st_mode))
+ err_exit(errno, "%s: not a regular file", path);
+ }
+
+ if (lseek_on_eintr(*fd, 0, SEEK_CUR, 1, 1) == (off_t)-1)
+ err_exit(errno, "%s: file not seekable", path);
+
errno = saved_errno;
}
@@ -705,7 +679,7 @@ rootfs(void)
global_fs.rootfd = -1;
open_on_eintr("/", &global_fs.rootfd,
- O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0400);
+ O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0400, NULL);
if (global_fs.rootfd < 0)
return NULL;
@@ -717,6 +691,10 @@ rootfs(void)
}
/* filesystem sandboxing in userspace
+ * TODO:
+ missing length bound check.
+ potential CPU DoS on very long paths, spammed repeatedly.
+ perhaps cap at PATH_LEN?
*/
int
fs_resolve_at(int dirfd, const char *path, int flags)
@@ -780,6 +758,15 @@ err:
return -1;
}
+/* NOTE:
+ rejects . and .. but not empty strings
+ after normalisation. edge case:
+ //////
+
+ normalised implicitly, but might be good
+ to add a defensive check regardless. code
+ probably not exploitable in current state.
+ */
int
fs_next_component(const char **p,
char *name, size_t namesz)