From owner-freebsd-current@FreeBSD.ORG Wed Dec 1 06:35:30 2004 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DCBAB16A4CE for ; Wed, 1 Dec 2004 06:35:30 +0000 (GMT) Received: from shuttle.wide.toshiba.co.jp (shuttle.wide.toshiba.co.jp [202.249.10.124]) by mx1.FreeBSD.org (Postfix) with ESMTP id 61B1243D5A for ; Wed, 1 Dec 2004 06:35:30 +0000 (GMT) (envelope-from jinmei@isl.rdc.toshiba.co.jp) Received: from ocean.jinmei.org (unknown [2001:200:0:8002:200:39ff:fed7:e2e4]) by shuttle.wide.toshiba.co.jp (Postfix) with ESMTP id 3F5FA15210; Wed, 1 Dec 2004 15:35:29 +0900 (JST) Date: Wed, 01 Dec 2004 15:35:39 +0900 Message-ID: From: JINMEI Tatuya / =?ISO-2022-JP?B?GyRCP0BMQEMjOkgbKEI=?= To: davids@webmaster.com In-Reply-To: References: User-Agent: Wanderlust/2.10.1 (Watching The Wheels) Emacs/21.3 Mule/5.0 (SAKAKI) Organization: Research & Development Center, Toshiba Corp., Kawasaki, Japan. MIME-Version: 1.0 (generated by SEMI 1.14.5 - "Awara-Onsen") Content-Type: text/plain; charset=US-ASCII cc: current@FreeBSD.org Subject: Re: malloc(0) returns an invalid address X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Dec 2004 06:35:31 -0000 >>>>> On Tue, 30 Nov 2004 21:40:25 -0800, >>>>> "David Schwartz" said: >> % ./a.out >> address of p is 0x800 >> zsh: 794 segmentation fault (core dumped) ./a.out >> >> Is this a malloc bug? Or is this the intended behavior and the man >> page description is old? > This is the intended behavior but the man page description is correct. The > problem is not that the pointer is invalid but that you assumed that it was > large enough to hold a 'char' and it is not. I know the line of XXX is not correct; I simply tried to highlight the problem, but I seem to convey the real point. How about this example? main() { char *p = malloc(0), *q; printf("address of p is %p\n", p); printf("the value of p is %c\n", *p); } the execution of this code would be like this: % ./a.out address of p is 0x800 zsh: 645 segmentation fault (core dumped) ./a.out And, more specifically, my real-world problem is that 'ndp -r' fails when it calls sysctl without any IPv6 default routers. The related code of ndp is as follows: int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST }; (...) if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) { err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); /*NOTREACHED*/ } buf = malloc(l); if (!buf) { err(1, "malloc"); /*NOTREACHED*/ } if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); /*NOTREACHED*/ } The first call to sysctl sets 'l' to 0, since the list is empty. Then the malloc returns '0x800' as a *valid pointer*. But in the second call to sysctl, kernel rejects this pointer at line 1299 of sys/kern/kern_sysctl.c: userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval) { (...) if (old) { --> if (!useracc(old, req.oldlen, VM_PROT_WRITE)) --> return (EFAULT); and so we'll see % ndp -r ndp: sysctl(ICMPV6CTL_ND6_DRLIST): Bad address Note that the same code worked with, e.g., FreeBSD 4.10. So, if we wanted to call 0x800 "a valid pointer just with not-enough-size", it would be fine. But then we need to implement the same logic in the kernel to provide consistent behavior. (I would "fix" the malloc behavior though). JINMEI, Tatuya Communication Platform Lab. Corporate R&D Center, Toshiba Corp. jinmei@isl.rdc.toshiba.co.jp