[V3 PATCH 03/16] powerpc/vas: Create take/drop task reference functions

2021-04-17 Thread Haren Myneni


Take task reference when each window opens and drops during close.
This functionality is needed for powerNV and pseries. So this patch
defines the existing code as functions in common book3s platform
vas-api.c

Signed-off-by: Haren Myneni 
---
 arch/powerpc/include/asm/vas.h  | 20 
 arch/powerpc/platforms/book3s/vas-api.c | 51 ++
 arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
 arch/powerpc/platforms/powernv/vas-window.c | 57 ++---
 arch/powerpc/platforms/powernv/vas.h|  6 +--
 5 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 6bbade60d8f4..2daaa1a2a9a9 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,9 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include 
+#include 
+#include 
 #include 
 
 
@@ -60,6 +63,22 @@ struct vas_user_win_ops {
int (*close_win)(void *);
 };
 
+struct vas_win_task {
+   struct pid *pid;/* Thread group ID of owner */
+   struct pid *tgid;   /* Linux process mm_struct */
+   struct mm_struct *mm;   /* Linux process mm_struct */
+};
+
+static inline void vas_drop_reference_task(struct vas_win_task *task)
+{
+   /* Drop references to pid and mm */
+   put_pid(task->pid);
+   if (task->mm) {
+   mm_context_remove_vas_window(task->mm);
+   mmdrop(task->mm);
+   }
+}
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -190,4 +209,5 @@ int vas_register_coproc_api(struct module *mod, enum 
vas_cop_type cop_type,
struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
+int vas_reference_task(struct vas_win_task *vtask);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c 
b/arch/powerpc/platforms/book3s/vas-api.c
index 05d7b99acf41..d98caa734154 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -60,6 +60,57 @@ static char *coproc_devnode(struct device *dev, umode_t 
*mode)
return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
 }
 
+/*
+ * Take reference to pid and mm
+ */
+int vas_reference_task(struct vas_win_task *vtask)
+{
+   /*
+* Window opened by a 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.
+*/
+   vtask->pid = get_task_pid(current, PIDTYPE_PID);
+   /*
+* Acquire a reference to the task's mm.
+*/
+   vtask->mm = get_task_mm(current);
+   if (!vtask->mm) {
+   put_pid(vtask->pid);
+   pr_err("VAS: pid(%d): mm_struct is not found\n",
+   current->pid);
+   return -EPERM;
+   }
+
+   mmgrab(vtask->mm);
+   mmput(vtask->mm);
+   mm_context_add_vas_window(vtask->mm);
+   /*
+* Process closes window during exit. In the case of
+* multithread application, the child thread 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.
+*/
+   vtask->tgid = find_get_pid(task_tgid_vnr(current));
+   /*
+* Even a process that has no foreign real address mapping can
+* use an unpaired COPY instruction (to no real effect). Issue
+* CP_ABORT to clear any pending COPY and prevent a covert
+* channel.
+*
+* __switch_to() will issue CP_ABORT on future context switches
+* if process / thread has any open VAS window (Use
+* current->mm->context.vas_windows).
+*/
+   asm volatile(PPC_CP_ABORT);
+
+   return 0;
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c 
b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..a4835cb82c09 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
 * NX user space windows can not be opened for task->mm=NULL
 * and faults will not be generated for kernel requests.
 */
-   if (WARN_ON_ONCE(!window->mm || !window->user_win))
+   if (WARN_ON_ONCE(!window->task.mm || !window->user_win))
return;
 
csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
@@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
csb.address = crb->stamp.nx.fault_storage_addr;
csb.flags = 0

[V2 PATCH 03/16] powerpc/vas: Create take/drop task reference functions

2021-04-13 Thread Haren Myneni


Take task reference when each window opens and drops during close.
This functionality is needed for powerNV and pseries. So this patch
defines the existing code as functions in powerpc platform
independent vas-api.c

Signed-off-by: Haren Myneni 
---
 arch/powerpc/include/asm/vas.h  | 20 
 arch/powerpc/kernel/vas-api.c   | 51 ++
 arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
 arch/powerpc/platforms/powernv/vas-window.c | 57 ++---
 arch/powerpc/platforms/powernv/vas.h|  6 +--
 5 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 6bbade60d8f4..2daaa1a2a9a9 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,9 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include 
+#include 
+#include 
 #include 
 
 
@@ -60,6 +63,22 @@ struct vas_user_win_ops {
int (*close_win)(void *);
 };
 
+struct vas_win_task {
+   struct pid *pid;/* Thread group ID of owner */
+   struct pid *tgid;   /* Linux process mm_struct */
+   struct mm_struct *mm;   /* Linux process mm_struct */
+};
+
+static inline void vas_drop_reference_task(struct vas_win_task *task)
+{
+   /* Drop references to pid and mm */
+   put_pid(task->pid);
+   if (task->mm) {
+   mm_context_remove_vas_window(task->mm);
+   mmdrop(task->mm);
+   }
+}
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -190,4 +209,5 @@ int vas_register_coproc_api(struct module *mod, enum 
vas_cop_type cop_type,
struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
+int vas_reference_task(struct vas_win_task *vtask);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/kernel/vas-api.c b/arch/powerpc/kernel/vas-api.c
index 05d7b99acf41..d98caa734154 100644
--- a/arch/powerpc/kernel/vas-api.c
+++ b/arch/powerpc/kernel/vas-api.c
@@ -60,6 +60,57 @@ static char *coproc_devnode(struct device *dev, umode_t 
*mode)
return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
 }
 
+/*
+ * Take reference to pid and mm
+ */
+int vas_reference_task(struct vas_win_task *vtask)
+{
+   /*
+* Window opened by a 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.
+*/
+   vtask->pid = get_task_pid(current, PIDTYPE_PID);
+   /*
+* Acquire a reference to the task's mm.
+*/
+   vtask->mm = get_task_mm(current);
+   if (!vtask->mm) {
+   put_pid(vtask->pid);
+   pr_err("VAS: pid(%d): mm_struct is not found\n",
+   current->pid);
+   return -EPERM;
+   }
+
+   mmgrab(vtask->mm);
+   mmput(vtask->mm);
+   mm_context_add_vas_window(vtask->mm);
+   /*
+* Process closes window during exit. In the case of
+* multithread application, the child thread 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.
+*/
+   vtask->tgid = find_get_pid(task_tgid_vnr(current));
+   /*
+* Even a process that has no foreign real address mapping can
+* use an unpaired COPY instruction (to no real effect). Issue
+* CP_ABORT to clear any pending COPY and prevent a covert
+* channel.
+*
+* __switch_to() will issue CP_ABORT on future context switches
+* if process / thread has any open VAS window (Use
+* current->mm->context.vas_windows).
+*/
+   asm volatile(PPC_CP_ABORT);
+
+   return 0;
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c 
b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..a4835cb82c09 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
 * NX user space windows can not be opened for task->mm=NULL
 * and faults will not be generated for kernel requests.
 */
-   if (WARN_ON_ONCE(!window->mm || !window->user_win))
+   if (WARN_ON_ONCE(!window->task.mm || !window->user_win))
return;
 
csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
@@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
csb.address = crb->stamp.nx.fault_storage_addr;
csb.flags = 0;
 
-   pid = window->pid;
+   

[PATCH 03/16] powerpc/vas: Create take/drop task reference functions

2021-04-10 Thread Haren Myneni


Take task reference when each window opens and drops during close.
This functionality is needed for powerNV and pseries. So this patch
defines the existing code as functions in powerpc platform
independent vas-api.c

Signed-off-by: Haren Myneni 
---
 arch/powerpc/include/asm/vas.h  | 20 
 arch/powerpc/kernel/vas-api.c   | 51 ++
 arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
 arch/powerpc/platforms/powernv/vas-window.c | 57 ++---
 arch/powerpc/platforms/powernv/vas.h|  6 +--
 5 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 6bbade60d8f4..2daaa1a2a9a9 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,9 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include 
+#include 
+#include 
 #include 
 
 
@@ -60,6 +63,22 @@ struct vas_user_win_ops {
int (*close_win)(void *);
 };
 
+struct vas_win_task {
+   struct pid *pid;/* Thread group ID of owner */
+   struct pid *tgid;   /* Linux process mm_struct */
+   struct mm_struct *mm;   /* Linux process mm_struct */
+};
+
+static inline void vas_drop_reference_task(struct vas_win_task *task)
+{
+   /* Drop references to pid and mm */
+   put_pid(task->pid);
+   if (task->mm) {
+   mm_context_remove_vas_window(task->mm);
+   mmdrop(task->mm);
+   }
+}
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -190,4 +209,5 @@ int vas_register_coproc_api(struct module *mod, enum 
vas_cop_type cop_type,
struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
+int vas_reference_task(struct vas_win_task *vtask);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/kernel/vas-api.c b/arch/powerpc/kernel/vas-api.c
index 05d7b99acf41..d98caa734154 100644
--- a/arch/powerpc/kernel/vas-api.c
+++ b/arch/powerpc/kernel/vas-api.c
@@ -60,6 +60,57 @@ static char *coproc_devnode(struct device *dev, umode_t 
*mode)
return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
 }
 
+/*
+ * Take reference to pid and mm
+ */
+int vas_reference_task(struct vas_win_task *vtask)
+{
+   /*
+* Window opened by a 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.
+*/
+   vtask->pid = get_task_pid(current, PIDTYPE_PID);
+   /*
+* Acquire a reference to the task's mm.
+*/
+   vtask->mm = get_task_mm(current);
+   if (!vtask->mm) {
+   put_pid(vtask->pid);
+   pr_err("VAS: pid(%d): mm_struct is not found\n",
+   current->pid);
+   return -EPERM;
+   }
+
+   mmgrab(vtask->mm);
+   mmput(vtask->mm);
+   mm_context_add_vas_window(vtask->mm);
+   /*
+* Process closes window during exit. In the case of
+* multithread application, the child thread 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.
+*/
+   vtask->tgid = find_get_pid(task_tgid_vnr(current));
+   /*
+* Even a process that has no foreign real address mapping can
+* use an unpaired COPY instruction (to no real effect). Issue
+* CP_ABORT to clear any pending COPY and prevent a covert
+* channel.
+*
+* __switch_to() will issue CP_ABORT on future context switches
+* if process / thread has any open VAS window (Use
+* current->mm->context.vas_windows).
+*/
+   asm volatile(PPC_CP_ABORT);
+
+   return 0;
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c 
b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..a4835cb82c09 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
 * NX user space windows can not be opened for task->mm=NULL
 * and faults will not be generated for kernel requests.
 */
-   if (WARN_ON_ONCE(!window->mm || !window->user_win))
+   if (WARN_ON_ONCE(!window->task.mm || !window->user_win))
return;
 
csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
@@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
csb.address = crb->stamp.nx.fault_storage_addr;
csb.flags = 0;
 
-   pid = window->pid;
+