summaryrefslogtreecommitdiff
blob: d42b4edbf66086198d17345548023ea6ee4a7ef1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 7f312d8..1eb686b 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -697,6 +697,33 @@ config HZ
 	default 1200 if HZ_1200
 	default 1024

+config ALPHA_UAC_SYSCTL
+       bool "Configure UAC policy via sysctl"
+       depends on SYSCTL
+       default y
+       ---help---
+         Configuring the UAC (unaligned access control) policy on a Linux
+         system usually involves setting a compile time define. If you say
+         Y here, you will be able to modify the UAC policy at runtime using
+         the /proc interface.
+
+         The UAC policy defines the action Linux should take when an
+         unaligned memory access occurs. The action can include printing a
+         warning message (NOPRINT), sending a signal to the offending
+         program to help developers debug their applications (SIGBUS), or
+         disabling the transparent fixing (NOFIX).
+
+         The sysctls will be initialized to the compile-time defined UAC
+         policy. You can change these manually, or with the sysctl(8)
+         userspace utility.
+
+         To disable the warning messages at runtime, you would use
+
+           echo 1 > /proc/sys/kernel/uac/noprint
+
+         This is pretty harmless. Say Y if you're not sure.
+
+
 source "drivers/pci/Kconfig"
 source "drivers/eisa/Kconfig"

diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 74aceea..cb35d80 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -103,6 +103,49 @@ static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
 			   "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
 #endif

+#ifdef CONFIG_ALPHA_UAC_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int enabled_noprint = 0;
+static int enabled_sigbus = 0;
+static int enabled_nofix = 0;
+
+struct ctl_table uac_table[] = {
+       {
+               .procname       = "noprint",
+               .data           = &enabled_noprint,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       {
+               .procname       = "sigbus",
+               .data           = &enabled_sigbus,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       {
+               .procname       = "nofix",
+               .data           = &enabled_nofix,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       { }
+};
+
+static int __init init_uac_sysctl(void)
+{
+   /* Initialize sysctls with the #defined UAC policy */
+   enabled_noprint = (test_thread_flag (TS_UAC_NOPRINT)) ? 1 : 0;
+   enabled_sigbus = (test_thread_flag (TS_UAC_SIGBUS)) ? 1 : 0;
+   enabled_nofix = (test_thread_flag (TS_UAC_NOFIX)) ? 1 : 0;
+   return 0;
+}
+#endif
+
 static void
 dik_show_code(unsigned int *pc)
 {
@@ -785,7 +828,12 @@ do_entUnaUser(void __user * va, unsigned long opcode,
 	/* Check the UAC bits to decide what the user wants us to do
 	   with the unaliged access.  */

+#ifndef CONFIG_ALPHA_UAC_SYSCTL
 	if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
+#else  /* CONFIG_ALPHA_UAC_SYSCTL */
+	if (!(current_thread_info()->status & TS_UAC_NOPRINT) &&
+	    !(enabled_noprint)) {
+#endif /* CONFIG_ALPHA_UAC_SYSCTL */
 		if (__ratelimit(&ratelimit)) {
 			printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
 			       current->comm, task_pid_nr(current),
@@ -1090,3 +1138,6 @@ trap_init(void)
 	wrent(entSys, 5);
 	wrent(entDbg, 6);
 }
+#ifdef CONFIG_ALPHA_UAC_SYSCTL
+       __initcall(init_uac_sysctl);
+#endif
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 87b2fc3..55021a8 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -152,6 +152,11 @@ static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
 #ifdef CONFIG_INOTIFY_USER
 #include <linux/inotify.h>
 #endif
+
+#ifdef CONFIG_ALPHA_UAC_SYSCTL
+extern struct ctl_table uac_table[];
+#endif
+
 #ifdef CONFIG_SPARC
 #endif

@@ -1844,6 +1849,13 @@ static struct ctl_table debug_table[] = {
 		.extra2		= &one,
 	},
 #endif
+#ifdef CONFIG_ALPHA_UAC_SYSCTL
+	{
+	        .procname   = "uac",
+		.mode       = 0555,
+	        .child      = uac_table,
+	 },
+#endif /* CONFIG_ALPHA_UAC_SYSCTL */
 	{ }
 };