diff options
| author | Ali Ahmet Memis <ali@iusegentoo.com> | 2026-08-21 01:45:27 +0000 |
|---|---|---|
| committer | Stafford Horne <shorne@gmail.com> | 2026-08-29 07:32:26 +0100 |
| commit | 78004e9a87f240df03e2f73120d291763c32e0a7 (patch) | |
| tree | 137c22dd795222931b9d2bf2501d37cd766741aa /fs/nls/nls_utf8.c | |
| download | linux-stable-78004e9a87f240df03e2f73120d291763c32e0a7.tar.gz linux-stable-78004e9a87f240df03e2f73120d291763c32e0a7.zip | |
openrisc: fix arbitrary kernel memory access via or1k_atomic syscallgrafted
sys_or1k_atomic() (syscall 244 in the "or1k" ABI) takes two user
pointers, v1 and v2, and swaps the words they point to in hand-written
assembly.
l.lwz r29,0(r4)
l.lwz r27,0(r5)
l.sw 0(r4),r27
l.sw 0(r5),r29
The pointers are not checked with access_ok(). The four memory
accesses also have no exception table entries.
A caller passes a kernel address as either pointer, and the syscall
reads from and writes to it directly.
This gives an unprivileged process a kernel read/write primitive. It
overwrites kernel data such as the sys_call_table, gaining code
execution in kernel context.
Check both pointers before entering the critical section. Add fixups
for the four memory accesses so faults on valid but unmapped user
addresses return -EFAULT.
[shorne@gmail.com: fix comment style]
Fixes: 9d02a4283e9c ("OpenRISC: Boot code")
Cc: stable@vger.kernel.org
Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
Signed-off-by: Stafford Horne <shorne@gmail.com>
Diffstat (limited to 'fs/nls/nls_utf8.c')
| -rw-r--r-- | fs/nls/nls_utf8.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c new file mode 100644 index 000000000..a0fa0610e --- /dev/null +++ b/fs/nls/nls_utf8.c @@ -0,0 +1,68 @@ +/* + * Module for handling utf8 just like any other charset. + * By Urban Widmark 2000 + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/nls.h> +#include <linux/errno.h> + +static unsigned char identity[256]; + +static int uni2char(wchar_t uni, unsigned char *out, int boundlen) +{ + int n; + + if (boundlen <= 0) + return -ENAMETOOLONG; + + n = utf32_to_utf8(uni, out, boundlen); + if (n < 0) { + *out = '?'; + return -EINVAL; + } + return n; +} + +static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) +{ + int n; + unicode_t u; + + n = utf8_to_utf32(rawstring, boundlen, &u); + if (n < 0 || u > MAX_WCHAR_T) { + *uni = 0x003f; /* ? */ + return -EINVAL; + } + *uni = (wchar_t) u; + return n; +} + +static struct nls_table table = { + .charset = "utf8", + .uni2char = uni2char, + .char2uni = char2uni, + .charset2lower = identity, /* no conversion */ + .charset2upper = identity, +}; + +static int __init init_nls_utf8(void) +{ + int i; + for (i=0; i<256; i++) + identity[i] = i; + + return register_nls(&table); +} + +static void __exit exit_nls_utf8(void) +{ + unregister_nls(&table); +} + +module_init(init_nls_utf8) +module_exit(exit_nls_utf8) +MODULE_DESCRIPTION("NLS UTF-8"); +MODULE_LICENSE("Dual BSD/GPL"); |
