From aoyama@peach.ne.jp  Sun Jan 31 01:35:02 2010
Return-Path: <aoyama@peach.ne.jp>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 35C2C106566B
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 31 Jan 2010 01:35:02 +0000 (UTC)
	(envelope-from aoyama@peach.ne.jp)
Received: from moon.peach.ne.jp (unknown [IPv6:2001:380:e06:127::53])
	by mx1.freebsd.org (Postfix) with ESMTP id C75A58FC0A
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 31 Jan 2010 01:35:01 +0000 (UTC)
Received: from moon.peach.ne.jp (localhost [127.0.0.1])
	by moon.peach.ne.jp (Postfix) with ESMTP id 4E4AD78C4B
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 31 Jan 2010 10:34:51 +0900 (JST)
Received: from hera.peach.ne.jp.private (unknown [192.168.2.36])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by moon.peach.ne.jp (Postfix) with ESMTP id 097CE78C3B
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 31 Jan 2010 10:34:50 +0900 (JST)
Received: from hera.peach.ne.jp.private (localhost [127.0.0.1])
	by hera.peach.ne.jp.private (8.14.3/8.14.3) with ESMTP id o0V1YZG4041031
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 31 Jan 2010 10:34:35 +0900 (JST)
	(envelope-from aoyama@peach.ne.jp)
Received: (from aoyama@localhost)
	by hera.peach.ne.jp.private (8.14.3/8.14.3/Submit) id o0V1YZDI041030;
	Sun, 31 Jan 2010 10:34:35 +0900 (JST)
	(envelope-from aoyama)
Message-Id: <201001310134.o0V1YZDI041030@hera.peach.ne.jp.private>
Date: Sun, 31 Jan 2010 10:34:35 +0900 (JST)
From: Daisuke Aoyama <aoyama@peach.ne.jp>
Reply-To: Daisuke Aoyama <aoyama@peach.ne.jp>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: fdisk(8) cannot handle above 1TB under i386 system.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         143389
>Category:       bin
>Synopsis:       [2tb] [patch] fdisk(8) cannot handle above 1TB under i386 system.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jan 31 01:40:08 UTC 2010
>Closed-Date:    
>Last-Modified:  Wed Oct 27 12:58:36 UTC 2010
>Originator:     Daisuke Aoyama
>Release:        FreeBSD 7.1-RELEASE-p10 i386
>Organization:
>Environment:
System: FreeBSD hera.peach.ne.jp.private 7.1-RELEASE-p10 FreeBSD 7.1-RELEASE-p10 #0: Wed Jan 13 13:18:46 JST 2010 aoyama@hera.peach.ne.jp.private:/usr/src/sys/i386/compile/ISCSI i386


	
>Description:
I first noticed at the post of FreeNAS forum below.
http://sourceforge.net/apps/phpbb/freenas/viewtopic.php?f=78&t=5558&start=0

The reason is /sbin/fdisk reads config value by strtol(3) as signed long which is 32 bits on i386.
At least, this bug still exists in HEAD.

structure definition:
 >>typedef struct cmd {
 >>    char                cmd;
 >>    int                 n_args;
 >>    struct arg {
 >>        char    argtype;
 >>        int     arg_val;		//signed int (32bit)
 >>    }                   args[MAX_ARGS];
 >>} CMD;
 
 in function parse_config_line():
 >> command->args[command->n_args].arg_val = strtol(cp, &end, 0);  // return as signed long
 
 strtol(3) is overflow if the value > LONG_MAX(0x7fffffffL on i386).
 As a result, the partition have wrong size and boundary.
 Once wrong partition is created, writing to it will cause data loss of next/previous partition.
 
 I tested following config on 2TB disk.
 
 g c261083 h255 s63
 p 1 165 1 2097152
 p 2 165 2097154 4175429632
 p 3 165 4177526787 16777216
 p 4 0 0 0
 a 1
 
 Please see above the link for more detail.
 I am not checking other utilities.
>How-To-Repeat:
/sbin/fdisk -f <above config> on 2TB disk.
>Fix:
use unsigned long/int or more wide type.
(strtoul, etc)
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Feb 1 04:31:53 UTC 2010 
Responsible-Changed-Why:  
This does not sound i386-specific. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=143389 

From: Mark Linimon <linimon@lonesome.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/143389: [2tb] fdisk(8) cannot handle above 1TB under i386
	system.
Date: Mon, 1 Feb 2010 00:34:29 -0600

 ----- Forwarded message from Garrett Cooper <yanefbsd@gmail.com> -----
 
 Subject: Re: bin/143389: [2tb] fdisk(8) cannot handle above 1TB under i386 
 	system.
 From: Garrett Cooper <yanefbsd@gmail.com>
 To: linimon@freebsd.org
 Cc: freebsd-i386@freebsd.org, freebsd-bugs@freebsd.org
 
     It's actually 32-bit specific, which includes i386, mips* [today],
 and powerpc.
 Cheers,
 -Garrett
 
 ----- End forwarded message -----

From: Mark Johnston <mjohnston@sandvine.com>
To: "bug-followup@FreeBSD.org" <bug-followup@FreeBSD.org>,
	"aoyama@peach.ne.jp" <aoyama@peach.ne.jp>
Cc:  
Subject: Re: bin/143389: [2tb] fdisk(8) cannot handle above 1TB under i386
 system.
Date: Tue, 26 Oct 2010 18:43:42 +0000

 I was about to submit a PR about this before I found this one.
 
 The problem is that fdisk is using a signed integer to store slice
 sizes, so attempts to create a slice of size >1TB will result in
 fdisk using LONG_MAX as the slice size...which ends up corresponding
 to 1TB on platforms where sizeof(long) =3D=3D 4.
 
 The solution is to use an unsigned long instead.
 
 We have a patch in our tree for it.
 
 Thanks,
 -Mark
 
 diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c
 index 0b2ce7d..89b35f9 100644
 --- a/sbin/fdisk/fdisk.c
 +++ b/sbin/fdisk/fdisk.c
 @@ -105,9 +105,9 @@ typedef struct cmd {
      char               cmd;
      int                        n_args;
      struct arg {
 -       char    argtype;
 -       int     arg_val;
 -       char    *arg_str;
 +       char            argtype;
 +       unsigned long   arg_val;
 +       char            *arg_str;
      }                  args[MAX_ARGS];
  } CMD;
 =20
 @@ -979,7 +979,7 @@ parse_config_line(char *line, CMD *command)
             if (isalpha(*cp))
                 command->args[command->n_args].argtype =3D *cp++;
             end =3D NULL;
 -           command->args[command->n_args].arg_val =3D strtol(cp, &end, 0);
 +           command->args[command->n_args].arg_val =3D strtoul(cp, &end, 0)=
 ;
             if (cp =3D=3D end || (!isspace(*end) && *end !=3D '\0')) {
                 char ch;
                 end =3D cp;
>Unformatted:
