Subject: kern/13516: sys/lib/libsa/read.c fails with elf files on raw devices
To: None <gnats-bugs@gnats.netbsd.org>
From: David Querbach <querbach@realtime.bc.ca>
List: netbsd-bugs
Date: 07/19/2001 19:37:06
>Number: 13516
>Category: kern
>Synopsis: libsa read() fails with elf files on raw devices
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 19 19:34:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: David Querbach
>Release: current-20010719
>Organization:
Real-Time Systems Inc.
>Environment:
System: NetBSD qingdao 1.5.1 NetBSD 1.5.1 (RAID) #0: Tue Jul 17 22:25:40 PDT 2001 root@qingdao:/usr/src/sys/arch/i386/compile/RAID i386
>Description:
The function exec_elf() in sys/lib/libsa/loadfile.c issues small
reads, some of which have starting offsets not divisible by the disk
block size DEV_BSIZE. If the boot device was opened in F_RAW mode
(as for an in() in-kernel image), these read requests are passed
directly to the function read() in sys/lib/libsa/read.c.
The function read() then rounds the offsets to a multiple of
DEV_BSIZE, which causes garbage to be returned to exec_elf, which
then chokes on it.
>How-To-Repeat:
Build a standalone which returns a NULL filename from devopen,
indicating that the device is a raw device.
>Fix:
Add deblocking code to detect offsets not divisible by DEV_BSIZE,
and fetch the enclosing block into a local buffer, then satisfy the
read from this local buffer.
Apply this patch to sys/lib/libsa/read.c:
Index: read.c
===================================================================
RCS file: /cvsroot/syssrc/sys/lib/libsa/read.c,v
retrieving revision 1.10
diff -c -r1.10 read.c
*** read.c 2000/03/30 12:19:48 1.10
--- read.c 2001/07/20 02:35:36
***************
*** 88,102 ****
#endif
#if !defined(LIBSA_NO_RAW_ACCESS)
if (f->f_flags & F_RAW) {
#if !defined(LIBSA_NO_TWIDDLE)
twiddle();
#endif
! errno = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
! btodb(f->f_offset), bcount, dest, &resid);
! if (errno)
! return (-1);
! f->f_offset += resid;
! return (resid);
}
#endif
resid = bcount;
--- 88,129 ----
#endif
#if !defined(LIBSA_NO_RAW_ACCESS)
if (f->f_flags & F_RAW) {
+ char *dst;
+
#if !defined(LIBSA_NO_TWIDDLE)
twiddle();
#endif
! dst = (char *)dest;
! while (bcount) {
! size_t blk, off, rem, cnt, res;
!
! blk = btodb(f->f_offset);
! off = f->f_offset - dbtob(blk);
! rem = DEV_BSIZE - off;
! cnt = (bcount < rem) ? bcount : rem;
!
! if (off == 0 && cnt == DEV_BSIZE) {
! errno = DEV_STRATEGY(f->f_dev)(f->f_devdata,
! F_READ, blk, DEV_BSIZE, dst, &res);
! if (errno)
! return (-1);
! }
! else {
! char buf[DEV_BSIZE];
!
! errno = DEV_STRATEGY(f->f_dev)(f->f_devdata,
! F_READ, blk, DEV_BSIZE, buf, &res);
! if (errno)
! return (-1);
! memcpy(dst, buf + off, cnt);
! }
!
! cnt = (res < cnt) ? res : cnt;
! f->f_offset += cnt;
! dst += cnt;
! bcount -= cnt;
! }
! return (dst - (char*)dest);
}
#endif
resid = bcount;
>Release-Note:
>Audit-Trail:
>Unformatted: