[PATCH v8 08/14] powerpc/vas: Take reference to PID and mm for user space windows
Nicholas Piggin
npiggin at gmail.com
Mon Mar 23 13:34:19 AEDT 2020
Haren Myneni's on March 19, 2020 4:16 pm:
>
> When process opens a window, its pid and tgid will be saved in vas_window
> struct. This window will be closed when the process exits. Kernel handles
> NX faults by updating CSB or send SEGV signal to pid if user space csb_addr
> is invalid.
Bit of a nitpick, but can you use articles consistently ("the", "a")? I
won't keep nitpicking changelogs but I think they could be made easier
to read. I'm happy to help proof read and suggest things offline when
you're happy with the technical content of them, let me know.
>
> In multi-thread applications, a window can be opened by child thread, but
> it will not be closed when this thread exits. Expects parent to clean up
> all resources including NX windows. Child thread can send requests using
> this window and can be killed before they are completed. But the pid
> assigned to this thread can be reused for other task while requests are
> pending. If the csb_addr passed in these requests is invalid, kernel will
> end up sending signal to the wrong task.
>
> To prevent reusing the pid, take references to pid and mm when the window
> is opened and release them during window close.
We went over this together a while back, but task management isn't
something I look at every day and it's complicated and easy to introduce
bugs. I suggest if we can get the changelog and comments written well
and understandable for someone who does not know or care about vas,
then cc linux-kernel and the maintainers, and hopefully someone will
take a look. It's not a large patch so if assumptions and concurrency
etc is documented, then it shouldn't be too much work.
Thanks,
Nick
>
> Signed-off-by: Haren Myneni <haren at linux.ibm.com>
> ---
> arch/powerpc/platforms/powernv/vas-debug.c | 2 +-
> arch/powerpc/platforms/powernv/vas-window.c | 53 ++++++++++++++++++++++++++---
> arch/powerpc/platforms/powernv/vas.h | 9 ++++-
> 3 files changed, 57 insertions(+), 7 deletions(-)
>
> diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c
> index 09e63df..ef9a717 100644
> --- a/arch/powerpc/platforms/powernv/vas-debug.c
> +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> @@ -38,7 +38,7 @@ static int info_show(struct seq_file *s, void *private)
>
> seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
> window->tx_win ? "Send" : "Receive");
> - seq_printf(s, "Pid : %d\n", window->pid);
> + seq_printf(s, "Pid : %d\n", vas_window_pid(window));
>
> unlock:
> mutex_unlock(&vas_mutex);
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
> index acb6a22..e7641a5 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -12,6 +12,8 @@
> #include <linux/log2.h>
> #include <linux/rcupdate.h>
> #include <linux/cred.h>
> +#include <linux/sched/mm.h>
> +#include <linux/mmu_context.h>
> #include <asm/switch_to.h>
> #include <asm/ppc-opcode.h>
> #include "vas.h"
> @@ -876,8 +878,6 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop,
> rxwin->user_win = rxattr->user_win;
> rxwin->cop = cop;
> rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT;
> - if (rxattr->user_win)
> - rxwin->pid = task_pid_vnr(current);
>
> init_winctx_for_rxwin(rxwin, rxattr, &winctx);
> init_winctx_regs(rxwin, &winctx);
> @@ -1027,7 +1027,6 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
> txwin->tx_win = 1;
> txwin->rxwin = rxwin;
> txwin->nx_win = txwin->rxwin->nx_win;
> - txwin->pid = attr->pid;
> txwin->user_win = attr->user_win;
> txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
>
> @@ -1068,8 +1067,43 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
> goto free_window;
> }
>
> - set_vinst_win(vinst, txwin);
> + if (txwin->user_win) {
> + /*
> + * Window opened by child thread may not be closed when
> + * it exits. So take reference to its pid and release it
> + * when the window is free by parent thread.
> + * Acquire a reference to the task's pid to make sure
> + * pid will not be re-used - needed only for multithread
> + * applications.
> + */
> + txwin->pid = get_task_pid(current, PIDTYPE_PID);
> + /*
> + * Acquire a reference to the task's mm.
> + */
> + txwin->mm = get_task_mm(current);
>
> + if (!txwin->mm) {
> + put_pid(txwin->pid);
> + pr_err("VAS: pid(%d): mm_struct is not found\n",
> + current->pid);
> + rc = -EPERM;
> + goto free_window;
> + }
> +
> + mmgrab(txwin->mm);
> + mmput(txwin->mm);
> + mm_context_add_copro(txwin->mm);
> + /*
> + * Process closes window during exit. In the case of
> + * multithread application, child can open window and
> + * can exit without closing it. Expects parent thread
> + * to use and close the window. So do not need to take
> + * pid reference for parent thread.
> + */
> + txwin->tgid = find_get_pid(task_tgid_vnr(current));
> + }
> +
> + set_vinst_win(vinst, txwin);
> return txwin;
>
> free_window:
> @@ -1266,8 +1300,17 @@ int vas_win_close(struct vas_window *window)
> poll_window_castout(window);
>
> /* if send window, drop reference to matching receive window */
> - if (window->tx_win)
> + if (window->tx_win) {
> + if (window->user_win) {
> + /* Drop references to pid and mm */
> + put_pid(window->pid);
> + if (window->mm) {
> + mm_context_remove_copro(window->mm);
> + mmdrop(window->mm);
> + }
> + }
> put_rx_win(window->rxwin);
> + }
>
> vas_window_free(window);
>
> diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
> index 310b8a0..16aa8ec 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -353,7 +353,9 @@ struct vas_window {
> bool user_win; /* True if user space window */
> void *hvwc_map; /* HV window context */
> void *uwc_map; /* OS/User window context */
> - pid_t pid; /* Linux process id of owner */
> + struct pid *pid; /* Linux process id of owner */
> + struct pid *tgid; /* Thread group ID of owner */
> + struct mm_struct *mm; /* Linux process mm_struct */
> int wcreds_max; /* Window credits */
>
> char *dbgname;
> @@ -431,6 +433,11 @@ struct vas_winctx {
> extern struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
> uint32_t pswid);
>
> +static inline int vas_window_pid(struct vas_window *window)
> +{
> + return pid_vnr(window->pid);
> +}
> +
> static inline void vas_log_write(struct vas_window *win, char *name,
> void *regptr, u64 val)
> {
> --
> 1.8.3.1
>
>
>
>
More information about the Linuxppc-dev
mailing list