[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