@@ -400,6 +400,18 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
400400 int rc ;
401401
402402 dev_dbg (& pdev -> dev , "%s called\n" , __func__ );
403+
404+ /*
405+ * Due to an erratum in some of the devices supported by the driver,
406+ * direct user submission to the device can be unsafe.
407+ * (See the INTEL-SA-01084 security advisory)
408+ *
409+ * For the devices that exhibit this behavior, require that the user
410+ * has CAP_SYS_RAWIO capabilities.
411+ */
412+ if (!idxd -> user_submission_safe && !capable (CAP_SYS_RAWIO ))
413+ return - EPERM ;
414+
403415 rc = check_vma (wq , vma , __func__ );
404416 if (rc < 0 )
405417 return rc ;
@@ -414,6 +426,70 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
414426 vma -> vm_page_prot );
415427}
416428
429+ static int idxd_submit_user_descriptor (struct idxd_user_context * ctx ,
430+ struct dsa_hw_desc __user * udesc )
431+ {
432+ struct idxd_wq * wq = ctx -> wq ;
433+ struct idxd_dev * idxd_dev = & wq -> idxd -> idxd_dev ;
434+ const uint64_t comp_addr_align = is_dsa_dev (idxd_dev ) ? 0x20 : 0x40 ;
435+ void __iomem * portal = idxd_wq_portal_addr (wq );
436+ struct dsa_hw_desc descriptor __aligned (64 );
437+ int rc ;
438+
439+ rc = copy_from_user (& descriptor , udesc , sizeof (descriptor ));
440+ if (rc )
441+ return - EFAULT ;
442+
443+ /*
444+ * DSA devices are capable of indirect ("batch") command submission.
445+ * On devices where direct user submissions are not safe, we cannot
446+ * allow this since there is no good way for us to verify these
447+ * indirect commands.
448+ */
449+ if (is_dsa_dev (idxd_dev ) && descriptor .opcode == DSA_OPCODE_BATCH &&
450+ !wq -> idxd -> user_submission_safe )
451+ return - EINVAL ;
452+ /*
453+ * As per the programming specification, the completion address must be
454+ * aligned to 32 or 64 bytes. If this is violated the hardware
455+ * engine can get very confused (security issue).
456+ */
457+ if (!IS_ALIGNED (descriptor .completion_addr , comp_addr_align ))
458+ return - EINVAL ;
459+
460+ if (wq_dedicated (wq ))
461+ iosubmit_cmds512 (portal , & descriptor , 1 );
462+ else {
463+ descriptor .priv = 0 ;
464+ descriptor .pasid = ctx -> pasid ;
465+ rc = idxd_enqcmds (wq , portal , & descriptor );
466+ if (rc < 0 )
467+ return rc ;
468+ }
469+
470+ return 0 ;
471+ }
472+
473+ static ssize_t idxd_cdev_write (struct file * filp , const char __user * buf , size_t len ,
474+ loff_t * unused )
475+ {
476+ struct dsa_hw_desc __user * udesc = (struct dsa_hw_desc __user * )buf ;
477+ struct idxd_user_context * ctx = filp -> private_data ;
478+ ssize_t written = 0 ;
479+ int i ;
480+
481+ for (i = 0 ; i < len /sizeof (struct dsa_hw_desc ); i ++ ) {
482+ int rc = idxd_submit_user_descriptor (ctx , udesc + i );
483+
484+ if (rc )
485+ return written ? written : rc ;
486+
487+ written += sizeof (struct dsa_hw_desc );
488+ }
489+
490+ return written ;
491+ }
492+
417493static __poll_t idxd_cdev_poll (struct file * filp ,
418494 struct poll_table_struct * wait )
419495{
@@ -436,6 +512,7 @@ static const struct file_operations idxd_cdev_fops = {
436512 .open = idxd_cdev_open ,
437513 .release = idxd_cdev_release ,
438514 .mmap = idxd_cdev_mmap ,
515+ .write = idxd_cdev_write ,
439516 .poll = idxd_cdev_poll ,
440517};
441518
0 commit comments