NetBSD Problem Report #47126

From  Fri Oct 26 06:37:52 2012
Return-Path: <>
Received: from ( [])
	by (Postfix) with ESMTP id 0199D63CA81
	for <>; Fri, 26 Oct 2012 06:37:51 +0000 (UTC)
Message-Id: <>
Date: Fri, 26 Oct 2012 06:19:57 +0000 (UTC)
Subject: i386 sudo fails on NetBSD amd64 kernel
X-Send-Pr-Version: 3.95

>Number:         47126
>Category:       pkg
>Synopsis:       i386 sudo fails on NetBSD amd64 kernel
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Oct 26 06:40:01 +0000 2012
>Originator:     Alan Barrett
>Release:        NetBSD 6.99.14
Not much
pkgsrc/security/sudo-1.7.9p1, compiled under NetBSD/i386,
running under NetBSD-6.99.14/amd64
	The get_process_ttyname function in sudo's ttyname.c source file
	uses sysctl([CTL_KERN, KERN_PROC, KERN_PROC_PID, ...], ...)
	to get a struct kinfo_proc, and then analyses it to try to find the
	name of the process's controlling terminal. terminal.

	struct kinfo_proc contains data types whose size changes on
        NetBSD between i386 and amd64.  When the data is supplied by an
        amd64 kernel, and analysed by code that ws expecting data from an
        i386 kernel, it fails.

	Install NetBSD/i386.  Build and install sudo from pkgrc.
	Build and boot a NetBSD/amd64 kernel, while keeping the
	old i386 sudo program.  Try to run sudo.  See it fail with
	this message:

	sudo: internal error, tried to erealloc(0)

        What happens is that sudo calls sysctl with a buffer
        large enough for an i386 struct kinfo_proc.  sysctl fails
        with ENOMEM because the amd64 structure is bigger, and
        (correctly) sets the size variable to zero.  sudo then
        loops with the intent to trying again with a larger buffer
        size, but the size is now zero, so it hits an error case
        in the erealloc function.

	1) Mishandling the size in the sysctl retry loop is clearly a
	bug in sudo.  Change it to keep track of the size better:

        do {
+           size_t oldsize;
            size += size / 10;
            ki_proc = erealloc(ki_proc, size);
+           oldsize = size;
            rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
+           if (size < oldsize)
+               size = oldsize;
        } while (rc == -1 && errno == ENOMEM);

	2) Returning an amd64 struct kinfo_proc to an i386 process
	is a broblem, but not really a kernel bug.  The NetBSD kernel already
	has struct kinfo_proc2, which is intended to have a
	machine-independent size.  sudo could use a different sysctl
	mib to retrieve struct kinfo_proc2 instead of struct kinfo_proc.

	3) It might be reasonable to replace all the kernel memory
	grovelling with a simple call to ttyname(3) on a fd that
	has been opened to /dev/tty, like this:

+ * Return a string from ttyname() containing the tty to which the process is
+ * attached or NULL if there is no tty associated with the process.
+ */
+char *
+    int ttyfd;
+    char *tty;
+    ttyfd = open("/dev/tty", O_RDONLY);
+    if (ttyfd < 0)
+       return NULL;
+    tty = ttyname(ttyfd);
+    close(ttyfd);
+    return (tty ? estrdup(tty) : NULL);

	It would also be possible to use something similar to the
	above code to augment, rather than replace, the
	other versions of get_process_ttyname that are already
	present in sudo's ttyname.c.

	Unfortunately, devname(3) can return "/dev/tty" instead
	of the actual name of the underlying device.  On NetBSD,
	it returns the name of the underlying device if it's a
	pty, but not if it's a hardware tty.

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD:,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.