diff options
| -rw-r--r-- | arch/ia64/kernel/unaligned.c | 31 | ||||
| -rw-r--r-- | include/linux/sysctl.h | 1 | ||||
| -rw-r--r-- | kernel/sysctl.c | 14 |
3 files changed, 43 insertions, 3 deletions
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 112913896844..1e357550c776 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c | |||
| @@ -53,6 +53,15 @@ dump (const char *str, void *vp, size_t len) | |||
| 53 | #define SIGN_EXT9 0xffffffffffffff00ul | 53 | #define SIGN_EXT9 0xffffffffffffff00ul |
| 54 | 54 | ||
| 55 | /* | 55 | /* |
| 56 | * sysctl settable hook which tells the kernel whether to honor the | ||
| 57 | * IA64_THREAD_UAC_NOPRINT prctl. Because this is user settable, we want | ||
| 58 | * to allow the super user to enable/disable this for security reasons | ||
| 59 | * (i.e. don't allow attacker to fill up logs with unaligned accesses). | ||
| 60 | */ | ||
| 61 | int no_unaligned_warning; | ||
| 62 | static int noprint_warning; | ||
| 63 | |||
| 64 | /* | ||
| 56 | * For M-unit: | 65 | * For M-unit: |
| 57 | * | 66 | * |
| 58 | * opcode | m | x6 | | 67 | * opcode | m | x6 | |
| @@ -1324,8 +1333,9 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) | |||
| 1324 | if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) | 1333 | if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) |
| 1325 | goto force_sigbus; | 1334 | goto force_sigbus; |
| 1326 | 1335 | ||
| 1327 | if (!(current->thread.flags & IA64_THREAD_UAC_NOPRINT) | 1336 | if (!no_unaligned_warning && |
| 1328 | && within_logging_rate_limit()) | 1337 | !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) && |
| 1338 | within_logging_rate_limit()) | ||
| 1329 | { | 1339 | { |
| 1330 | char buf[200]; /* comm[] is at most 16 bytes... */ | 1340 | char buf[200]; /* comm[] is at most 16 bytes... */ |
| 1331 | size_t len; | 1341 | size_t len; |
| @@ -1340,7 +1350,22 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) | |||
| 1340 | if (user_mode(regs)) | 1350 | if (user_mode(regs)) |
| 1341 | tty_write_message(current->signal->tty, buf); | 1351 | tty_write_message(current->signal->tty, buf); |
| 1342 | buf[len-1] = '\0'; /* drop '\r' */ | 1352 | buf[len-1] = '\0'; /* drop '\r' */ |
| 1343 | printk(KERN_WARNING "%s", buf); /* watch for command names containing %s */ | 1353 | /* watch for command names containing %s */ |
| 1354 | printk(KERN_WARNING "%s", buf); | ||
| 1355 | } else { | ||
| 1356 | if (no_unaligned_warning && !noprint_warning) { | ||
| 1357 | noprint_warning = 1; | ||
| 1358 | printk(KERN_WARNING "%s(%d) encountered an " | ||
| 1359 | "unaligned exception which required\n" | ||
| 1360 | "kernel assistance, which degrades " | ||
| 1361 | "the performance of the application.\n" | ||
| 1362 | "Unaligned exception warnings have " | ||
| 1363 | "been disabled by the system " | ||
| 1364 | "administrator\n" | ||
| 1365 | "echo 0 > /proc/sys/kernel/ignore-" | ||
| 1366 | "unaligned-usertrap to re-enable\n", | ||
| 1367 | current->comm, current->pid); | ||
| 1368 | } | ||
| 1344 | } | 1369 | } |
| 1345 | } else { | 1370 | } else { |
| 1346 | if (within_logging_rate_limit()) | 1371 | if (within_logging_rate_limit()) |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 0e92bf7ec28e..bac61db26456 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
| @@ -147,6 +147,7 @@ enum | |||
| 147 | KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */ | 147 | KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */ |
| 148 | KERN_SPIN_RETRY=70, /* int: number of spinlock retries */ | 148 | KERN_SPIN_RETRY=70, /* int: number of spinlock retries */ |
| 149 | KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */ | 149 | KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */ |
| 150 | KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */ | ||
| 150 | }; | 151 | }; |
| 151 | 152 | ||
| 152 | 153 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c05a2b7125e1..acf6c1550f27 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -124,6 +124,10 @@ extern int sysctl_hz_timer; | |||
| 124 | extern int acct_parm[]; | 124 | extern int acct_parm[]; |
| 125 | #endif | 125 | #endif |
| 126 | 126 | ||
| 127 | #ifdef CONFIG_IA64 | ||
| 128 | extern int no_unaligned_warning; | ||
| 129 | #endif | ||
| 130 | |||
| 127 | static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, | 131 | static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, |
| 128 | ctl_table *, void **); | 132 | ctl_table *, void **); |
| 129 | static int proc_doutsstring(ctl_table *table, int write, struct file *filp, | 133 | static int proc_doutsstring(ctl_table *table, int write, struct file *filp, |
| @@ -666,6 +670,16 @@ static ctl_table kern_table[] = { | |||
| 666 | .proc_handler = &proc_dointvec, | 670 | .proc_handler = &proc_dointvec, |
| 667 | }, | 671 | }, |
| 668 | #endif | 672 | #endif |
| 673 | #ifdef CONFIG_IA64 | ||
| 674 | { | ||
| 675 | .ctl_name = KERN_IA64_UNALIGNED, | ||
| 676 | .procname = "ignore-unaligned-usertrap", | ||
| 677 | .data = &no_unaligned_warning, | ||
| 678 | .maxlen = sizeof (int), | ||
| 679 | .mode = 0644, | ||
| 680 | .proc_handler = &proc_dointvec, | ||
| 681 | }, | ||
| 682 | #endif | ||
| 669 | { .ctl_name = 0 } | 683 | { .ctl_name = 0 } |
| 670 | }; | 684 | }; |
| 671 | 685 | ||
