aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2007-02-10 04:45:24 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:29 -0500
commit34f5a39899f3f3e815da64f48ddb72942d86c366 (patch)
tree447f8c019786a28801909a7af60bf088566d1925
parenta136e99f12cdc967a6f607644e471ed749f963db (diff)
[PATCH] Add TAINT_USER and ability to set taint flags from userspace
Allow taint flags to be set from userspace by writing to /proc/sys/kernel/tainted, and add a new taint flag, TAINT_USER, to be used when userspace has potentially done something dangerous that might compromise the kernel. This will allow support personnel to ask further questions about what may have caused the user taint flag to have been set. For example, they might examine the logs of the realtime JVM to see if the Java program has used the really silly, stupid, dangerous, and completely-non-portable direct access to physical memory feature which MUST be implemented according to the Real-Time Specification for Java (RTSJ). Sigh. What were those silly people at Sun thinking? [akpm@osdl.org: build fix] [bunk@stusta.de: cleanup] Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/kernel.h1
-rw-r--r--kernel/panic.c6
-rw-r--r--kernel/sysctl.c27
3 files changed, 30 insertions, 4 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 63fb18dcac30..e1a429ada97f 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -200,6 +200,7 @@ extern enum system_states {
200#define TAINT_FORCED_RMMOD (1<<3) 200#define TAINT_FORCED_RMMOD (1<<3)
201#define TAINT_MACHINE_CHECK (1<<4) 201#define TAINT_MACHINE_CHECK (1<<4)
202#define TAINT_BAD_PAGE (1<<5) 202#define TAINT_BAD_PAGE (1<<5)
203#define TAINT_USER (1<<6)
203 204
204extern void dump_stack(void); 205extern void dump_stack(void);
205 206
diff --git a/kernel/panic.c b/kernel/panic.c
index 525e365f7239..623d1828259a 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -150,6 +150,7 @@ EXPORT_SYMBOL(panic);
150 * 'R' - User forced a module unload. 150 * 'R' - User forced a module unload.
151 * 'M' - Machine had a machine check experience. 151 * 'M' - Machine had a machine check experience.
152 * 'B' - System has hit bad_page. 152 * 'B' - System has hit bad_page.
153 * 'U' - Userspace-defined naughtiness.
153 * 154 *
154 * The string is overwritten by the next call to print_taint(). 155 * The string is overwritten by the next call to print_taint().
155 */ 156 */
@@ -158,13 +159,14 @@ const char *print_tainted(void)
158{ 159{
159 static char buf[20]; 160 static char buf[20];
160 if (tainted) { 161 if (tainted) {
161 snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c", 162 snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
162 tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', 163 tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
163 tainted & TAINT_FORCED_MODULE ? 'F' : ' ', 164 tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
164 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', 165 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
165 tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', 166 tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
166 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', 167 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
167 tainted & TAINT_BAD_PAGE ? 'B' : ' '); 168 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
169 tainted & TAINT_USER ? 'U' : ' ');
168 } 170 }
169 else 171 else
170 snprintf(buf, sizeof(buf), "Not tainted"); 172 snprintf(buf, sizeof(buf), "Not tainted");
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 16ef870fa75a..7733ef58aaca 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -151,6 +151,8 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
151#ifdef CONFIG_PROC_SYSCTL 151#ifdef CONFIG_PROC_SYSCTL
152static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, 152static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
153 void __user *buffer, size_t *lenp, loff_t *ppos); 153 void __user *buffer, size_t *lenp, loff_t *ppos);
154static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
155 void __user *buffer, size_t *lenp, loff_t *ppos);
154#endif 156#endif
155 157
156static ctl_table root_table[]; 158static ctl_table root_table[];
@@ -174,6 +176,7 @@ extern ctl_table inotify_table[];
174int sysctl_legacy_va_layout; 176int sysctl_legacy_va_layout;
175#endif 177#endif
176 178
179
177static void *get_uts(ctl_table *table, int write) 180static void *get_uts(ctl_table *table, int write)
178{ 181{
179 char *which = table->data; 182 char *which = table->data;
@@ -344,14 +347,16 @@ static ctl_table kern_table[] = {
344 .proc_handler = &proc_dostring, 347 .proc_handler = &proc_dostring,
345 .strategy = &sysctl_string, 348 .strategy = &sysctl_string,
346 }, 349 },
350#ifdef CONFIG_PROC_SYSCTL
347 { 351 {
348 .ctl_name = KERN_TAINTED, 352 .ctl_name = KERN_TAINTED,
349 .procname = "tainted", 353 .procname = "tainted",
350 .data = &tainted, 354 .data = &tainted,
351 .maxlen = sizeof(int), 355 .maxlen = sizeof(int),
352 .mode = 0444, 356 .mode = 0644,
353 .proc_handler = &proc_dointvec, 357 .proc_handler = &proc_dointvec_taint,
354 }, 358 },
359#endif
355 { 360 {
356 .ctl_name = KERN_CAP_BSET, 361 .ctl_name = KERN_CAP_BSET,
357 .procname = "cap-bound", 362 .procname = "cap-bound",
@@ -1927,6 +1932,7 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
1927 1932
1928#define OP_SET 0 1933#define OP_SET 0
1929#define OP_AND 1 1934#define OP_AND 1
1935#define OP_OR 2
1930 1936
1931static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, 1937static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1932 int *valp, 1938 int *valp,
@@ -1938,6 +1944,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1938 switch(op) { 1944 switch(op) {
1939 case OP_SET: *valp = val; break; 1945 case OP_SET: *valp = val; break;
1940 case OP_AND: *valp &= val; break; 1946 case OP_AND: *valp &= val; break;
1947 case OP_OR: *valp |= val; break;
1941 } 1948 }
1942 } else { 1949 } else {
1943 int val = *valp; 1950 int val = *valp;
@@ -1970,6 +1977,22 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1970 do_proc_dointvec_bset_conv,&op); 1977 do_proc_dointvec_bset_conv,&op);
1971} 1978}
1972 1979
1980/*
1981 * Taint values can only be increased
1982 */
1983static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
1984 void __user *buffer, size_t *lenp, loff_t *ppos)
1985{
1986 int op;
1987
1988 if (!capable(CAP_SYS_ADMIN))
1989 return -EPERM;
1990
1991 op = OP_OR;
1992 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1993 do_proc_dointvec_bset_conv,&op);
1994}
1995
1973struct do_proc_dointvec_minmax_conv_param { 1996struct do_proc_dointvec_minmax_conv_param {
1974 int *min; 1997 int *min;
1975 int *max; 1998 int *max;