NetBSD Problem Report #58717

From www@netbsd.org  Sat Oct  5 08:52:20 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
	 client-signature RSA-PSS (2048 bits) client-digest SHA256)
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id E80281A923D
	for <gnats-bugs@gnats.NetBSD.org>; Sat,  5 Oct 2024 08:52:19 +0000 (UTC)
Message-Id: <20241005085218.6D87B1A923E@mollari.NetBSD.org>
Date: Sat,  5 Oct 2024 08:52:18 +0000 (UTC)
From: cryintothebluesky@gmail.com
Reply-To: cryintothebluesky@gmail.com
To: gnats-bugs@NetBSD.org
Subject: wm/cde crashes in ttsession during startup on sparc64
X-Send-Pr-Version: www-1.0

>Number:         58717
>Category:       pkg
>Synopsis:       wm/cde crashes in ttsession during startup on sparc64
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Oct 05 08:55:00 +0000 2024
>Last-Modified:  Sat Oct 05 12:30:02 +0000 2024
>Originator:     Sad Clouds
>Release:        pkg-2024Q2
>Organization:
>Environment:
>Description:
Pkgsrc wm/cde desktop has a number of issues on sparc64 and other architectures with LP64 data model.

The issue described in this bug occurs with ttsession executable, which crashes with SIGBUS due to alignment problems, where the original programmer assumed size of integer == size of long.
>How-To-Repeat:
Build wm/cde on sparc64 and then run /usr/pkg/bin/startcde
>Fix:
The patch below assumes that uid_t, gid_t, mode_t can be safely cast to unsigned int without data loss. Most platforms seem to define these types as either signed or unsigned 32-bit integer, so should be OK.

There are other executables like dthelpview which crash with SIGBUS, but at least with this patch CDE can be usable on sparc64.

--- cde-2.5.2/lib/tt/lib/db/db_server_xdr.C.orig	2023-11-18 22:38:09.000000000 +0000
+++ cde-2.5.2/lib/tt/lib/db/db_server_xdr.C	2024-10-05 06:59:06.723430670 +0100
@@ -108,7 +108,7 @@
 			 (xdrproc_t) xdr_keydesc)) {
 		return (FALSE);
 	}
-	if (!xdr_int(xdrs, &objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	if (!xdr_int(xdrs, &objp->isreclen)) {
@@ -168,7 +168,7 @@
 	if (!xdr_string(xdrs, &objp->path, 1024)) {
 		return (FALSE);
 	}
-	if (!xdr_int(xdrs, &objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	return (TRUE);
@@ -183,7 +183,7 @@
 	if (!xdr_array(xdrs, (char **)&objp->rec.rec_val, (u_int *)&objp->rec.rec_len, ISMAXRECLEN, sizeof(char), (xdrproc_t) xdr_char)) {
 		return (FALSE);
 	}
-	if (!xdr_int(xdrs, &objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->isrecnum)) {
@@ -242,7 +242,7 @@
 	if (!xdr_array(xdrs, (char **)&objp->rec.rec_val, (u_int *)&objp->rec.rec_len, ISMAXRECLEN, sizeof(char), (xdrproc_t)xdr_char)) {
 		return (FALSE);
 	}
-	if (!xdr_int(xdrs, &objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	return (TRUE);
@@ -380,13 +380,13 @@
 bool_t
 xdr_Tt_oidaccess_results(XDR *xdrs, _Tt_oidaccess_results *objp)
 {
-	if (!xdr_long(xdrs, (long *)&objp->uid)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->uid)) {
 		return (FALSE);
 	}
-	if (!xdr_long(xdrs, (long *)&objp->group)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->group)) {
 		return (FALSE);
 	}
-	if (!xdr_short(xdrs, (short *)&objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	if (!xdr_int(xdrs, &objp->result)) {
@@ -503,13 +503,13 @@
 bool_t
 xdr_tt_access(XDR *xdrs, _tt_access *objp)
 {
-	if (!xdr_long(xdrs, (long *)&objp->user)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->user)) {
 		return (FALSE);
 	}
-	if (!xdr_long(xdrs, (long *)&objp->group)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->group)) {
 		return (FALSE);
 	}
-	if (!xdr_u_long(xdrs, (unsigned long *)&objp->mode)) {
+	if (!xdr_u_int(xdrs, (unsigned *)&objp->mode)) {
 		return (FALSE);
 	}
 	return (TRUE);

>Audit-Trail:
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: pkg/58717: wm/cde crashes in ttsession during startup on sparc64
Date: Sat, 5 Oct 2024 12:03:16 +0200

 This needs more explanation and should be filed as an upstream bug report
 and be resolved properly.

 You seem to patch mostly signed int vs unsigned int issues, which should not
 matter at this level. I would even silence any compiler warnings about
 mismatches via -Wno-.... options.

 Then there are a few xdr_long -> xdr_u_int translations which probably
 prevent the crashes you talked about, but it is hard to tell without
 more context if those are correct. If the long was an error and the
 value actually is int (or unsigned int) those patches would be OK, but
 if the real value is long you now only encode half of the data - either
 the lower or upper half, and it might break _LP64 little endian
 architectures.

 But the original code already casting the pointer is a red flag - you
 basically *never* should cast in this context, or something else is
 very wrong.

 This code is ugly, and the real way to fix it probably is to create 
 xdr_* helper functions to use for all the relevant types, like:

 static bool_t
 xdr_uid(XDR *xdrs, cost uid_t *uid)
 {
 	if (sizeof(*uid) == sizeof(long))
 		xdr_long(xdrs, uid);
 	else if (sizeof(*uid) == sizeof(int))
 		xdr_int(xdrs, uid);
 	else
 		assert(false);
 }

 Would be a nice use for C++ templates :-)
 You could hide this in macros, but that obfuscates it even more.

 Martin

From: Sad Clouds <cryintothebluesky@gmail.com>
To: gnats-bugs@netbsd.org
Cc: "Martin Husemann via gnats" <gnats-admin@NetBSD.org>,
 pkg-manager@netbsd.org, gnats-admin@netbsd.org, pkgsrc-bugs@netbsd.org
Subject: Re: pkg/58717: wm/cde crashes in ttsession during startup on
 sparc64
Date: Sat, 5 Oct 2024 13:12:40 +0100

 I think originally, many Unix systems used long integer for uid_t and
 gid_t, however this results in different size on LP64 systems. See
 https://docs.oracle.com/cd/E18752_01/html/816-5138/appendixa-1.html

 Ideally they should have used fixed width integers, but the original
 implementation probably predates that version of C standard. I'm not
 aware of any platforms using full 64-bits for uid_t and gid_t. So even
 if those are defined as 64-bit integers, they should always contain
 values <= UINT32_MAX. So casting this from 64-bit to 32-bit should be
 safe and should not result in data loss. Now if this assumption is
 wrong, then using sizeof() for each type would be a better solution.

 I'm not sure there is a standard definition for uid_t, gid_t and
 mode_t. So these could be defined as signed or unsigned. Also I'm not
 sure if there is a difference in behavior between xdr_int() and
 xdr_u_int(), but it feels that using the unsigned conversion is
 probably safer and may avoid sign extension bugs.

From: Sad Clouds <cryintothebluesky@gmail.com>
To: gnats-bugs@netbsd.org
Cc: "Martin Husemann via gnats" <gnats-admin@NetBSD.org>,
 pkg-manager@netbsd.org, gnats-admin@netbsd.org, pkgsrc-bugs@netbsd.org
Subject: Re: pkg/58717: wm/cde crashes in ttsession during startup on
 sparc64
Date: Sat, 5 Oct 2024 13:26:57 +0100

 There is already a bug for this issue upstream which was created by
 somebody about a year ago:
 https://sourceforge.net/p/cdesktopenv/tickets/153/

 One of the developers used Qemu to simulate sparc64, but then if the
 emulator runs on x86 and allows unaligned loads/stores, then they would
 not have reproduced the exact issue.

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.