diff options
Diffstat (limited to 'arch/um/drivers/mconsole_kern.c')
| -rw-r--r-- | arch/um/drivers/mconsole_kern.c | 93 |
1 files changed, 52 insertions, 41 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 3df3bd544492..ff4bda95b9c7 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL */ #include <linux/console.h> @@ -12,7 +12,9 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/notifier.h> +#include <linux/panic_notifier.h> #include <linux/reboot.h> +#include <linux/sched/debug.h> #include <linux/proc_fs.h> #include <linux/slab.h> #include <linux/syscalls.h> @@ -24,7 +26,7 @@ #include <linux/fs.h> #include <linux/mount.h> #include <linux/file.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/switch_to.h> #include <init.h> @@ -35,6 +37,8 @@ #include "mconsole_kern.h" #include <os.h> +static struct vfsmount *proc_mnt = NULL; + static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) { @@ -95,7 +99,6 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) } if (!list_empty(&mc_requests)) schedule_work(&mconsole_work); - reactivate_fd(fd, MCONSOLE_IRQ); return IRQ_HANDLED; } @@ -123,17 +126,22 @@ void mconsole_log(struct mc_request *req) void mconsole_proc(struct mc_request *req) { - struct vfsmount *mnt = task_active_pid_ns(current)->proc_mnt; + struct vfsmount *mnt = proc_mnt; char *buf; int len; struct file *file; int first_chunk = 1; char *ptr = req->request.data; + loff_t pos = 0; ptr += strlen("proc"); ptr = skip_spaces(ptr); - file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); + if (!mnt) { + mconsole_reply(req, "Proc not available", 1, 0); + goto out; + } + file = file_open_root_mnt(mnt, ptr, O_RDONLY, 0); if (IS_ERR(file)) { mconsole_reply(req, "Failed to open file", 1, 0); printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); @@ -147,12 +155,7 @@ void mconsole_proc(struct mc_request *req) } do { - loff_t pos = file->f_pos; - mm_segment_t old_fs = get_fs(); - set_fs(KERNEL_DS); - len = vfs_read(file, buf, PAGE_SIZE - 1, &pos); - set_fs(old_fs); - file->f_pos = pos; + len = kernel_read(file, buf, PAGE_SIZE - 1, &pos); if (len < 0) { mconsole_reply(req, "Read of file failed", 1, 0); goto out_free; @@ -221,7 +224,7 @@ void mconsole_go(struct mc_request *req) void mconsole_stop(struct mc_request *req) { - deactivate_fd(req->originating_fd, MCONSOLE_IRQ); + block_signals(); os_set_fd_block(req->originating_fd, 1); mconsole_reply(req, "stopped", 0, 0); for (;;) { @@ -243,8 +246,8 @@ void mconsole_stop(struct mc_request *req) (*req->cmd->handler)(req); } os_set_fd_block(req->originating_fd, 0); - reactivate_fd(req->originating_fd, MCONSOLE_IRQ); mconsole_reply(req, "", 0, 0); + unblock_signals(); } static DEFINE_SPINLOCK(mc_devices_lock); @@ -280,7 +283,7 @@ struct unplugged_pages { }; static DEFINE_MUTEX(plug_mem_mutex); -static unsigned long long unplugged_pages_count = 0; +static unsigned long long unplugged_pages_count; static LIST_HEAD(unplugged_pages); static int unplug_index = UNPLUGGED_PER_PAGE; @@ -551,7 +554,7 @@ struct mconsole_output { static DEFINE_SPINLOCK(client_lock); static LIST_HEAD(clients); -static char console_buf[MCONSOLE_MAX_DATA]; +static char console_buf[MCONSOLE_MAX_DATA] __nonstring; static void console_write(struct console *console, const char *string, unsigned int len) @@ -564,7 +567,7 @@ static void console_write(struct console *console, const char *string, while (len > 0) { n = min((size_t) len, ARRAY_SIZE(console_buf)); - strncpy(console_buf, string, n); + memcpy(console_buf, string, n); string += n; len -= n; @@ -645,11 +648,9 @@ void mconsole_sysrq(struct mc_request *req) static void stack_proc(void *arg) { - struct task_struct *from = current, *to = arg; + struct task_struct *task = arg; - to->thread.saved_task = from; - rcu_user_hooks_switch(from, to); - switch_to(from, to, from); + show_stack(task, NULL, KERN_INFO); } /* @@ -690,6 +691,24 @@ void mconsole_stack(struct mc_request *req) with_console(req, stack_proc, to); } +static int __init mount_proc(void) +{ + struct file_system_type *proc_fs_type; + struct vfsmount *mnt; + + proc_fs_type = get_fs_type("proc"); + if (!proc_fs_type) + return -ENODEV; + + mnt = kern_mount(proc_fs_type); + put_filesystem(proc_fs_type); + if (IS_ERR(mnt)) + return PTR_ERR(mnt); + + proc_mnt = mnt; + return 0; +} + /* * Changed by mconsole_setup, which is __setup, and called before SMP is * active. @@ -703,6 +722,8 @@ static int __init mconsole_init(void) int err; char file[UNIX_PATH_MAX]; + mount_proc(); + if (umid_file_name("mconsole", file, sizeof(file))) return -1; snprintf(mconsole_socket_name, sizeof(file), "%s", file); @@ -719,7 +740,7 @@ static int __init mconsole_init(void) err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, IRQF_SHARED, "mconsole", (void *)sock); - if (err) { + if (err < 0) { printk(KERN_ERR "Failed to get IRQ for management console\n"); goto out; } @@ -750,27 +771,18 @@ static ssize_t mconsole_proc_write(struct file *file, { char *buf; - buf = kmalloc(count + 1, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - if (copy_from_user(buf, buffer, count)) { - count = -EFAULT; - goto out; - } - - buf[count] = '\0'; + buf = memdup_user_nul(buffer, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); - out: kfree(buf); return count; } -static const struct file_operations mconsole_proc_fops = { - .owner = THIS_MODULE, - .write = mconsole_proc_write, - .llseek = noop_llseek, +static const struct proc_ops mconsole_proc_ops = { + .proc_write = mconsole_proc_write, + .proc_lseek = noop_llseek, }; static int create_proc_mconsole(void) @@ -780,7 +792,7 @@ static int create_proc_mconsole(void) if (notify_socket == NULL) return 0; - ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops); + ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_ops); if (ent == NULL) { printk(KERN_INFO "create_proc_mconsole : proc_create failed\n"); return 0; @@ -834,13 +846,12 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); - return 0; + return NOTIFY_DONE; } static struct notifier_block panic_exit_notifier = { - .notifier_call = notify_panic, - .next = NULL, - .priority = 1 + .notifier_call = notify_panic, + .priority = INT_MAX, /* run as soon as possible */ }; static int add_notifier(void) |
