NetBSD Problem Report #44964

From campbell@mumble.net  Fri May 13 17:05:06 2011
Return-Path: <campbell@mumble.net>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id 84DB363C607
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 13 May 2011 17:05:06 +0000 (UTC)
Message-Id: <20110513170503.9A877982B6@pluto.mumble.net>
Date: Fri, 13 May 2011 17:05:03 +0000 (UTC)
From: Taylor R Campbell <campbell+netbsd@mumble.net>
Reply-To: Taylor R Campbell <campbell+netbsd@mumble.net>
To: gnats-bugs@gnats.NetBSD.org
Subject: cgd seems to panic on unaligned writes instead of giving EINVAL
X-Send-Pr-Version: 3.95

>Number:         44964
>Category:       kern
>Synopsis:       cgd seems to panic on unaligned writes instead of giving EINVAL
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 13 17:10:01 +0000 2011
>Closed-Date:    Sat Jun 04 16:41:44 +0000 2011
>Last-Modified:  Sat Jun 04 16:41:44 +0000 2011
>Originator:     Taylor R Campbell <campbell+netbsd@mumble.net>
>Release:        NetBSD 5.99.51
>Organization:
>Environment:
System: NetBSD oberon.local 5.99.51 NetBSD 5.99.51 (RIAMONODEBUG) #143: Sun May 8 19:13:30 UTC 2011 root@smalltalk.local:/home/riastradh/netbsd/current/obj/sys/arch/i386/compile/RIAMONODEBUG i386
Architecture: i386
Machine: i386
>Description:

	I was trying to take a snapshot of my old machine's disk and
	store it in a cgd partition on my new machine, transmitting the
	bits over the network.  On the new machine, I ran something
	like this:

		socat tcp4-listen:12345,bind=10.0.1.2,reuseaddr stdout \
		| dd if=/dev/stdin of=/dev/rcgd2d bs=1m

	On the old laptop, I ran something like this:

		dd if=/dev/rwd0d of=/dev/stdout bs=1m \
		| socat stdin tcp4:10.0.1.2:12345

	Whatever block size I specified on the new machine, it panicked
	-- very soon for large block sizes, and after a couple hours
	for bs=512 (the transfer was, uh, very slow with bs=512).  I
	suspect that this is because the blocks got cut up into
	randomly sized chunks in transit over the network, and dd
	happily relayed randomly sized chunks straight to cgd, which
	should have given EINVAL instead of panicking.

	The next morning I learned that `bs=N' is not, in fact, the
	same as `ibs=N obs=N'.  Thanks, POSIX.  WTF?

	Here's a gdb stack trace from a fault in rijndael_blockEncrypt.
	I belive the faulting address was 0xcc501000, which gdb
	helpfully reports is out of bounds.  Note the unusual value
	len=2896 in cgd_cipher.  I have the core dump, so if you want
	to see the values of any of the data structures (e.g., the
	struct buf in question), let me know.

#7  0xc010d13f in calltrap ()
#8  0xc06c9924 in rijndael_blockEncrypt (cipher=0xcf4226ac, key=0xc3465000,
    input=0xcc501000 <Address 0xcc501000 out of bounds>, inputLen=4096,
    outBuffer=<value optimized out>)
    at /home/riastradh/netbsd/current/src/sys/crypto/rijndael/rijndael-api-fst.c:136  
#9  0xc023f298 in aes_cbc_enc_int (privdata=0xcf422738, dst=0xc34ea000,
    src=0xcc501000, len=512)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd_crypto.c:209
#10 0xc023ec90 in cgd_cipher_uio_cbc (privdata=0xcf422738,
    cipher=0xc023f260 <aes_cbc_enc_int>, dstuio=0xcf4227d0, srcuio=0xcf4227b4)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd_crypto.c:115
#11 0xc023eee6 in cgd_cipher_aes_cbc (privdata=0xc3465000, dstuio=0xcf4227d0,
    srcuio=0xcf4227b4, iv=0xcf42281c, dir=-867168256)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd_crypto.c:235
#12 0xc023db25 in cgd_cipher (cs=0xcf39ef04, dstv=0xc34e9000, srcv=0xcc500000,
    len=2896, blkno=<value optimized out>, secsize=512, dir=2)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:904
#13 0xc023de9a in cgdstart (dksc=0xcf39ef08, bp=0xc322e790)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:392
#14 0xc028882d in dk_start (di=0xc0bd8a58, dksc=0xcf39ef08)
    at /home/riastradh/netbsd/current/src/sys/dev/dksubr.c:239
#15 0xc0288ab6 in dk_strategy (di=0xc0bd8a58, dksc=0xcf39ef08, bp=0xc322e790)
    at /home/riastradh/netbsd/current/src/sys/dev/dksubr.c:225
#16 0xc023e1d1 in cgdstrategy (bp=0xc322e790)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:297
#17 0xc051315c in physio (strategy=0xc023e190 <cgdstrategy>, obp=0x0,
    dev=23827, flags=0, min_phys=0xc0512e60 <minphys>, uio=0xcf422c7c)
    at /home/riastradh/netbsd/current/src/sys/kern/kern_physio.c:352
#18 0xc023d7b7 in cgdwrite (dev=23827, uio=0xcf422c7c, flags=592)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:496
#19 0xc0753627 in cdev_write (dev=23827, uio=0xcf422c7c, flag=592)
    at /home/riastradh/netbsd/current/src/sys/kern/subr_devsw.c:860
#20 0xc073ed07 in spec_write (v=0xcf422bf4)
    at /home/riastradh/netbsd/current/src/sys/miscfs/specfs/spec_vnops.c:666
#21 0xc089285d in VOP_WRITE (vp=0xcf0388c4, uio=0xcf422c7c, ioflag=592,
    cred=0xcf372480)
    at /home/riastradh/netbsd/current/src/sys/kern/vnode_if.c:431
#22 0xc0877f7f in vn_write (fp=0xcf371ac0, offset=0xcf371ac0, uio=0xcf422c7c,
    cred=0xcf372480, flags=1)
    at /home/riastradh/netbsd/current/src/sys/kern/vfs_vnops.c:566
#23 0xc0777413 in dofilewrite (fd=4, fp=0x0, buf=0xbb600000, nbyte=2896,
    offset=0xcf371ac0, flags=1, retval=0xcf422d28)
    at /home/riastradh/netbsd/current/src/sys/kern/sys_generic.c:357
#24 0xc0777540 in sys_write (l=0xcf3c02a0, uap=0xcf422d00, retval=0xcf422d28)
    at /home/riastradh/netbsd/current/src/sys/kern/sys_generic.c:325
#25 0xc0783079 in syscall (frame=0xcf422d48)
    at /home/riastradh/netbsd/current/src/sys/sys/syscallvar.h:61
#26 0xc01005d6 in syscall1 ()

	gdb stack trace from another panic.

#9  0xc07622e5 in panic (fmt=0xc0b19830 "cgd_cipher: len %% blocksize != 0")
    at /home/riastradh/netbsd/current/src/sys/kern/subr_prf.c:298
#10 0xc023dc75 in cgd_cipher (cs=0xcf2d8e0c, dstv=0xc36b0000, srcv=0xcc500000, 
    len=9608, blkno=<value optimized out>, secsize=512, dir=2)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:862
#11 0xc023de9a in cgdstart (dksc=0xcf2d8e10, bp=0xc33c3794)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:392
#12 0xc028882d in dk_start (di=0xc0bd8a58, dksc=0xcf2d8e10)
    at /home/riastradh/netbsd/current/src/sys/dev/dksubr.c:239
#13 0xc0288ab6 in dk_strategy (di=0xc0bd8a58, dksc=0xcf2d8e10, bp=0xc33c3794)
    at /home/riastradh/netbsd/current/src/sys/dev/dksubr.c:225
#14 0xc023e1d1 in cgdstrategy (bp=0xc33c3794)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:297
#15 0xc051315c in physio (strategy=0xc023e190 <cgdstrategy>, obp=0x0, 
    dev=23827, flags=0, min_phys=0xc0512e60 <minphys>, uio=0xcf86bc7c)
    at /home/riastradh/netbsd/current/src/sys/kern/kern_physio.c:352
#16 0xc023d7b7 in cgdwrite (dev=23827, uio=0xcf86bc7c, flags=592)
    at /home/riastradh/netbsd/current/src/sys/dev/cgd.c:496
#17 0xc0753627 in cdev_write (dev=23827, uio=0xcf86bc7c, flag=592)
    at /home/riastradh/netbsd/current/src/sys/kern/subr_devsw.c:860
#18 0xc073ed07 in spec_write (v=0xcf86bbf4)
    at /home/riastradh/netbsd/current/src/sys/miscfs/specfs/spec_vnops.c:666
#19 0xc089285d in VOP_WRITE (vp=0xd0016638, uio=0xcf86bc7c, ioflag=592, 
    cred=0xcf360300)
    at /home/riastradh/netbsd/current/src/sys/kern/vnode_if.c:431
#20 0xc0877f7f in vn_write (fp=0xcf361c00, offset=0xcf361c00, uio=0xcf86bc7c,
    cred=0xcf360300, flags=1)
    at /home/riastradh/netbsd/current/src/sys/kern/vfs_vnops.c:566
#21 0xc0777413 in dofilewrite (fd=4, fp=0x6, buf=0xbb800000, nbyte=9608,
    offset=0xcf361c00, flags=1, retval=0xcf86bd28)
    at /home/riastradh/netbsd/current/src/sys/kern/sys_generic.c:357
#22 0xc0777540 in sys_write (l=0xd8325800, uap=0xcf86bd00, retval=0xcf86bd28)
    at /home/riastradh/netbsd/current/src/sys/kern/sys_generic.c:325
#23 0xc0783079 in syscall (frame=0xcf86bd48)
    at /home/riastradh/netbsd/current/src/sys/sys/syscallvar.h:61
#24 0xc01005d6 in syscall1 ()

>How-To-Repeat:

	Write unaligned blocks to a cgd.  Hope you didn't have any
	important session state on your machine.

>Fix:

	Yes, please!

>Release-Note:

>Audit-Trail:
From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/44964: cgd seems to panic on unaligned writes instead of giving EINVAL
Date: Fri, 13 May 2011 22:00:10 -0400 (EDT)

 Should be fixed on revision rijndael-api-fst.c rev 1.21

 christos

From: Taylor R Campbell <campbell+netbsd@mumble.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/44964: cgd seems to panic on unaligned writes instead of giving EINVAL
Date: Sat, 14 May 2011 05:07:32 +0000

    Date: Sat, 14 May 2011 02:05:03 +0000 (UTC)
    From: christos@zoulas.com (Christos Zoulas)

    Should be fixed on revision rijndael-api-fst.c rev 1.21

 (1.22, presumably.)  I don't think this fully fixes the problem: other
 parts of cgd are not prepared to handle unaligned writes.  For
 example, cgd_cipher requires that len be an integral multiple of
 blocksize (by assertion) and an integral multiple of secsize (by
 subtracting secsize from the size_t len until len is zero).

 Also, I'm worried that using 8-bit operations rather than 32-bit
 operations will hurt performance; have you compared the performance
 before and after?

 How about the following patch to reject unaligned writes?  Untested,
 but I'll test it in the next couple days if I get a chance.

 Index: cgd.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/cgd.c,v
 retrieving revision 1.71
 diff -p -u -r1.71 cgd.c
 --- cgd.c	19 Nov 2010 06:44:39 -0000	1.71
 +++ cgd.c	14 May 2011 05:06:22 -0000
 @@ -293,6 +293,21 @@ cgdstrategy(struct buf *bp)

  	DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
  	    (long)bp->b_bcount));
 +
 +	/*
 +	 * Reject unaligned writes.  We can encrypt and decrypt only
 +	 * complete disk sectors, and we let the ciphers require their
 +	 * buffers to be aligned to 32-bit boundaries.
 +	 */
 +	if (bp->b_blkno < 0 ||
 +	    (bp->b_bcount % DEV_BSIZE) != 0 ||
 +	    ((uintptr_t)bp->b_data & 3) != 0) {
 +		bp->b_error = EINVAL;
 +		bp->b_resid = bp->b_bcount;
 +		biodone(bp);
 +		return;
 +	}
 +
  	/* XXXrcd: Should we test for (cs != NULL)? */
  	dk_strategy(di, &cs->sc_dksc, bp);
  	return;

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, kern-bug-people@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, 
	Taylor R Campbell <campbell+netbsd@mumble.net>
Cc: 
Subject: Re: kern/44964: cgd seems to panic on unaligned writes instead of giving EINVAL
Date: Sat, 14 May 2011 11:10:24 -0400

 On May 14,  5:15am, campbell+netbsd@mumble.net (Taylor R Campbell) wrote:
 -- Subject: Re: kern/44964: cgd seems to panic on unaligned writes instead of

 |  (1.22, presumably.)  I don't think this fully fixes the problem: other
 |  parts of cgd are not prepared to handle unaligned writes.  For
 |  example, cgd_cipher requires that len be an integral multiple of
 |  blocksize (by assertion) and an integral multiple of secsize (by
 |  subtracting secsize from the size_t len until len is zero).
 |  
 |  Also, I'm worried that using 8-bit operations rather than 32-bit
 |  operations will hurt performance; have you compared the performance
 |  before and after?

 I don't think that it is going to be that bad, because the code is
 using GETU32() PUTU32() in other parts to handle unaligned reads
 and writes which is even more expensive.
 |
 |  How about the following patch to reject unaligned writes?  Untested,
 |  but I'll test it in the next couple days if I get a chance.

 I agree, commit that patch. cgd will not work properly anyway. But I would
 also leave my patch in, because this was the only part of the code that
 did not handle unaligned buffers.

 christos

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/44964 CVS commit: src/sys/dev
Date: Thu, 19 May 2011 20:34:13 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Thu May 19 20:34:13 UTC 2011

 Modified Files:
 	src/sys/dev: cgd.c

 Log Message:
 Reject unaligned writes to cgd.

 Fixes the following PRs:

 PR kern/44515 (cgd dies on non-aligned writes to the raw device)
 PR kern/44964 (cgd seems to panic on unaligned writes instead of giving EINVAL)

 ok christos


 To generate a diff of this commit:
 cvs rdiff -u -r1.71 -r1.72 src/sys/dev/cgd.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/44964 CVS commit: src/tests/dev/cgd
Date: Thu, 19 May 2011 20:37:50 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Thu May 19 20:37:50 UTC 2011

 Modified Files:
 	src/tests/dev/cgd: t_cgd.sh

 Log Message:
 Expand tests for unaligned writes to cgd.  No more xfail.

 PR kern/44515
 PR kern/44964


 To generate a diff of this commit:
 cvs rdiff -u -r1.9 -r1.10 src/tests/dev/cgd/t_cgd.sh

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: jruoho@NetBSD.org
State-Changed-When: Sat, 04 Jun 2011 16:41:44 +0000
State-Changed-Why:

Thanks for fixing this.



>Unformatted:

NetBSD Home
NetBSD PR Database Search

(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.