Subject: bin/22394: [rkb] radioctl(1) -w gets SIGBUS on strict-alignment LP64 archs
To: None <gnats-bugs@gnats.netbsd.org>
From: None <rafal@netbsd.org>
List: netbsd-bugs
Date: 08/07/2003 13:32:33
>Number:         22394
>Category:       bin
>Synopsis:       radioctl(1) -w gets SIGBUS on strict-alignment LP64 archs
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 07 17:33:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Rafal Boni
>Release:        NetBSD 1.6W
>Organization:
Lacking
>Environment:
System: NetBSD fearless-vampire-killer.waterside.net 1.6W NetBSD 1.6W (FEARLESS_VAMPIRE_KILLER) #6: Thu Aug 7 12:24:53 EDT 2003 rafal@fearless-vampire-killer.waterside.net:/extra/sparc64/obj/sys/arch/sparc64/compile/FEARLESS_VAMPIRE_KILLER sparc64
Architecture: sparc64
Machine: sparc64

>Description:
	On sparc64 (or any LP64 strict-aligning arch), run the following
	command, and watch it fall over with a SIGBUS:

		radioctl -w frequency=88.1	(or any other frequency)

	The issue is that even though the fields of the radio_info structure
	are either int's or u_int32_t's, the radioctl(1) code that sets them
	passes a u_long pointer and a u_long value to the update function.

	A secondary issue is that the radioio.h interface uses pure `int'
	in some places and `u_int32_t' in others... it should probably be
	made to just use u_int32_t's everywhere to make like simpler.
>How-To-Repeat:
	Run the following on a sparc64 with a radio tuner (like a DLink
	USB radio):

		radioctl -w frequency=88.1	(or any other frequency)
	
	Watch SIGBUS happen and the value not get updated.
>Fix:

	Here's some cleanup to radioctl(1); as I mentioned, the radioio.h
	interface should probably *also* be changed to use fixed-size-types
	everywhere (I don't think this is an ABI issue).

Index: radioctl.c
===================================================================
RCS file: /cvsroot/src/usr.bin/radioctl/radioctl.c,v
retrieving revision 1.5
diff -u -r1.5 radioctl.c
--- radioctl.c	2003/06/23 13:05:51	1.5
+++ radioctl.c	2003/08/07 17:16:20
@@ -91,7 +91,7 @@
 
 static void	print_value(int);
 static void	change_value(const struct opt_t);
-static void	update_value(int, u_long *, u_long);
+static void	update_value(int, u_int32_t *, u_int32_t);
 
 static void     warn_unsupported(int);
 static void	usage(void);
@@ -260,14 +260,14 @@
 
 	switch (o.option) {
 	case OPTION_VOLUME:
-		update_value(o.sign, (u_long *)&ri.volume, o.value);
+		update_value(o.sign, &ri.volume, o.value);
 		break;
 	case OPTION_FREQUENCY:
-		update_value(o.sign, (u_long *)&ri.freq, o.value);
+		update_value(o.sign, &ri.freq, o.value);
 		break;
 	case OPTION_REFERENCE:
 		if (ri.caps & RADIO_CAPS_REFERENCE_FREQ)
-			update_value(o.sign, (u_long *)&ri.rfreq, o.value);
+			update_value(o.sign, &ri.rfreq, o.value);
 		else
 			unsupported++;
 		break;
@@ -281,7 +281,7 @@
 		break;
 	case OPTION_SENSITIVITY:
 		if (ri.caps & RADIO_CAPS_LOCK_SENSITIVITY)
-			update_value(o.sign, (u_long *)&ri.lock, o.value);
+			update_value(o.sign, &ri.lock, o.value);
 		else
 			unsupported++;
 		break;
@@ -320,7 +320,7 @@
 }
 
 static void
-update_value(int sign, u_long *value, u_long update)
+update_value(int sign, u_int32_t *value, u_int32_t update)
 {
 	switch (sign) {
 	case SIGN_NONE:
>Release-Note:
>Audit-Trail:
>Unformatted:
 		Sources from Aug 6th, 2003