diff options
author | Warner Losh <imp@FreeBSD.org> | 2024-03-11 20:15:24 +0000 |
---|---|---|
committer | Warner Losh <imp@FreeBSD.org> | 2024-04-16 19:54:29 +0000 |
commit | 519aef9045d00e0e2082d3096abef139b24623e9 (patch) | |
tree | c4685a3acee39e03c2b6121bc8622c343ebb4155 | |
parent | d18377cbb7233ca9a468728596718884c64d6cb1 (diff) |
kboot: hostfs -- check for llseek failure correctly
The host_* syscalls are all raw Linux system calls, not the POSIX
wrappers that glibc / musl create. So we have to ranage change the
return value of host_llseek correctly to use the negative value hack
that all Linux system calls use.
This fixes a false positive error detection when we do something like
lseek(fd, 0xf1234567, ...); This returns 0xf1234567, which is a negative
value which used to trigger the error path. Instead, we check using the
is_linux_error() and store the return value in a long. Translate that
errno to a host errno and set the global errno to that and return
-1. lseek can't otherwise return a negative number, since it's the
offset after seeking into the file, which by definition is positive.
This kept the 'read the UEFI memory map out of physical memory' from
working on aarch64 (whose boot loader falls back to reading it since
there are restrictive kernel options that can also prevent it), since
the physical address the memory map was at on my platform was like
0xfa008018.
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D44286
(cherry picked from commit d650c3efb638f1b2742429a5fb8e7c087839868b)
-rw-r--r-- | stand/kboot/kboot/hostfs.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/stand/kboot/kboot/hostfs.c b/stand/kboot/kboot/hostfs.c index 7c0600fc35a0..cfd3476b3c84 100644 --- a/stand/kboot/kboot/hostfs.c +++ b/stand/kboot/kboot/hostfs.c @@ -124,7 +124,7 @@ hostfs_seek(struct open_file *f, off_t offset, int whence) { hostfs_file *hf = f->f_fsdata; uint32_t offl, offh; - int err; + long err; uint64_t res; /* @@ -137,8 +137,15 @@ hostfs_seek(struct open_file *f, off_t offset, int whence) offl = res & 0xfffffffful; offh = (res >> 32) & 0xfffffffful; err = host_llseek(hf->hf_fd, offh, offl, &res, whence); - if (err < 0) - return (err); + /* + * Since we're interfacing to the raw linux system call, we have to + * carefully check. We have to translate the errno value from the host + * to libsa's conventions. + */ + if (is_linux_error(err)) { + errno = host_to_stand_errno(err); + return (-1); + } return (res); } |