NetBSD Problem Report #13516
Received: (qmail 14064 invoked from network); 20 Jul 2001 02:33:42 -0000
Message-Id: <200107200237.f6K2b6I08642@qingdao.realtime.bc.ca>
Date: Thu, 19 Jul 2001 19:37:06 -0700 (PDT)
From: David Querbach <querbach@realtime.bc.ca>
Reply-To: querbach@realtime.bc.ca
To: gnats-bugs@gnats.netbsd.org
Subject: sys/lib/libsa/read.c fails with elf files on raw devices
X-Send-Pr-Version: 3.95
>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: Fri Jul 20 02:34:00 +0000 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:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.