From owner-freebsd-current@FreeBSD.ORG Wed Dec 1 15:49:58 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 9B24216A4CE for ; Wed, 1 Dec 2004 15:49:58 +0000 (GMT) Received: from mail1.webmaster.com (mail1.webmaster.com [216.152.64.168]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5A4E443D31 for ; Wed, 1 Dec 2004 15:49:58 +0000 (GMT) (envelope-from davids@webmaster.com) Received: from however by webmaster.com (MDaemon.PRO.v7.1.0.R) with ESMTP id md50000305528.msg for ; Wed, 01 Dec 2004 07:26:13 -0800 From: "David Schwartz" To: Date: Wed, 1 Dec 2004 07:49:54 -0800 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.6604 (9.0.2911.0) Importance: Normal In-Reply-To: X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180 X-Authenticated-Sender: joelkatz@webmaster.com X-Spam-Processed: mail1.webmaster.com, Wed, 01 Dec 2004 07:26:13 -0800 (not processed: message from trusted or authenticated source) X-MDRemoteIP: 206.171.168.138 X-Return-Path: davids@webmaster.com X-MDaemon-Deliver-To: current@FreeBSD.org X-MDAV-Processed: mail1.webmaster.com, Wed, 01 Dec 2004 07:26:13 -0800 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 Reply-To: davids@webmaster.com 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 15:49:58 -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 This should fault. Although the return value of 'malloc(0)' is a valid pointer, once you cast it to a 'char *', you cannot dereference it because it does not point to a character. This same problem would occur with 'malloc(1)' and 'int *'. > 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). The malloc behavior is not broken, so it cannot be fixed. The kernel check semantics in 'useracc' are wrong for zero lengths. DS