summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 {
#define TAINT_FORCED_RMMOD (1<<3)
#define TAINT_MACHINE_CHECK (1<<4)
#define TAINT_BAD_PAGE (1<<5)
+#define TAINT_USER (1<<6)
extern void dump_stack(void);
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);
* 'R' - User forced a module unload.
* 'M' - Machine had a machine check experience.
* 'B' - System has hit bad_page.
+ * 'U' - Userspace-defined naughtiness.
*
* The string is overwritten by the next call to print_taint().
*/
@@ -158,13 +159,14 @@ const char *print_tainted(void)
{
static char buf[20];
if (tainted) {
- snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c",
+ snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
- tainted & TAINT_BAD_PAGE ? 'B' : ' ');
+ tainted & TAINT_BAD_PAGE ? 'B' : ' ',
+ tainted & TAINT_USER ? 'U' : ' ');
}
else
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,
#ifdef CONFIG_PROC_SYSCTL
static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
static ctl_table root_table[];
@@ -174,6 +176,7 @@ extern ctl_table inotify_table[];
int sysctl_legacy_va_layout;
#endif
+
static void *get_uts(ctl_table *table, int write)
{
char *which = table->data;
@@ -344,14 +347,16 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
},
+#ifdef CONFIG_PROC_SYSCTL
{
.ctl_name = KERN_TAINTED,
.procname = "tainted",
.data = &tainted,
.maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_taint,
},
+#endif
{
.ctl_name = KERN_CAP_BSET,
.procname = "cap-bound",
@@ -1927,6 +1932,7 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
#define OP_SET 0
#define OP_AND 1
+#define OP_OR 2
static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
int *valp,
@@ -1938,6 +1944,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
switch(op) {
case OP_SET: *valp = val; break;
case OP_AND: *valp &= val; break;
+ case OP_OR: *valp |= val; break;
}
} else {
int val = *valp;
@@ -1970,6 +1977,22 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
do_proc_dointvec_bset_conv,&op);
}
+/*
+ * Taint values can only be increased
+ */
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int op;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ op = OP_OR;
+ return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
+ do_proc_dointvec_bset_conv,&op);
+}
+
struct do_proc_dointvec_minmax_conv_param {
int *min;
int *max;