git: d650c3efb638 - main - kboot: hostfs -- check for llseek failure correctly

From: Warner Losh <imp_at_FreeBSD.org>
Date: Mon, 11 Mar 2024 21:23:25 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=d650c3efb638f1b2742429a5fb8e7c087839868b

commit d650c3efb638f1b2742429a5fb8e7c087839868b
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2024-03-11 20:15:24 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-03-11 21:21:51 +0000

    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
---
 stand/kboot/kboot/hostfs.c | 13 ++++++++++---
 1 file 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);
 }