Skip to content

Commit 6d33b30

Browse files
committed
Merge tag 'fsi-updates-2018-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/linux-fsi into char-misc-next
Ben writes: FSI Updates for 4.19 This adds two FSI fixes: - Fix a NULL dereference in the scom driver - Fix a command buffer size issue in the sbefifo driver that breaks some operations with POWER system debugger (cronus)
2 parents a39284a + 15e2a72 commit 6d33b30

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

drivers/fsi/fsi-sbefifo.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/delay.h>
3131
#include <linux/uio.h>
3232
#include <linux/vmalloc.h>
33+
#include <linux/mm.h>
3334

3435
/*
3536
* The SBEFIFO is a pipe-like FSI device for communicating with
@@ -110,7 +111,7 @@ enum sbe_state
110111
#define SBEFIFO_TIMEOUT_IN_RSP 1000
111112

112113
/* Other constants */
113-
#define SBEFIFO_MAX_CMD_LEN PAGE_SIZE
114+
#define SBEFIFO_MAX_USER_CMD_LEN (0x100000 + PAGE_SIZE)
114115
#define SBEFIFO_RESET_MAGIC 0x52534554 /* "RSET" */
115116

116117
struct sbefifo {
@@ -128,6 +129,7 @@ struct sbefifo {
128129
struct sbefifo_user {
129130
struct sbefifo *sbefifo;
130131
struct mutex file_lock;
132+
void *cmd_page;
131133
void *pending_cmd;
132134
size_t pending_len;
133135
};
@@ -726,7 +728,7 @@ int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len,
726728
return -ENODEV;
727729
if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC))
728730
return -ENODEV;
729-
if (!resp_len || !command || !response || cmd_len > SBEFIFO_MAX_CMD_LEN)
731+
if (!resp_len || !command || !response)
730732
return -EINVAL;
731733

732734
/* Prepare iov iterator */
@@ -751,6 +753,15 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
751753
/*
752754
* Char device interface
753755
*/
756+
757+
static void sbefifo_release_command(struct sbefifo_user *user)
758+
{
759+
if (is_vmalloc_addr(user->pending_cmd))
760+
vfree(user->pending_cmd);
761+
user->pending_cmd = NULL;
762+
user->pending_len = 0;
763+
}
764+
754765
static int sbefifo_user_open(struct inode *inode, struct file *file)
755766
{
756767
struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev);
@@ -762,8 +773,8 @@ static int sbefifo_user_open(struct inode *inode, struct file *file)
762773

763774
file->private_data = user;
764775
user->sbefifo = sbefifo;
765-
user->pending_cmd = (void *)__get_free_page(GFP_KERNEL);
766-
if (!user->pending_cmd) {
776+
user->cmd_page = (void *)__get_free_page(GFP_KERNEL);
777+
if (!user->cmd_page) {
767778
kfree(user);
768779
return -ENOMEM;
769780
}
@@ -816,7 +827,7 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
816827
/* Extract the response length */
817828
rc = len - iov_iter_count(&resp_iter);
818829
bail:
819-
user->pending_len = 0;
830+
sbefifo_release_command(user);
820831
mutex_unlock(&user->file_lock);
821832
return rc;
822833
}
@@ -831,13 +842,23 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
831842
if (!user)
832843
return -EINVAL;
833844
sbefifo = user->sbefifo;
834-
if (len > SBEFIFO_MAX_CMD_LEN)
845+
if (len > SBEFIFO_MAX_USER_CMD_LEN)
835846
return -EINVAL;
836847
if (len & 3)
837848
return -EINVAL;
838849

839850
mutex_lock(&user->file_lock);
840851

852+
/* Can we use the pre-allocate buffer ? If not, allocate */
853+
if (len <= PAGE_SIZE)
854+
user->pending_cmd = user->cmd_page;
855+
else
856+
user->pending_cmd = vmalloc(len);
857+
if (!user->pending_cmd) {
858+
rc = -ENOMEM;
859+
goto bail;
860+
}
861+
841862
/* Copy the command into the staging buffer */
842863
if (copy_from_user(user->pending_cmd, buf, len)) {
843864
rc = -EFAULT;
@@ -863,6 +884,9 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
863884
/* Update the staging buffer size */
864885
user->pending_len = len;
865886
bail:
887+
if (!user->pending_len)
888+
sbefifo_release_command(user);
889+
866890
mutex_unlock(&user->file_lock);
867891

868892
/* And that's it, we'll issue the command on a read */
@@ -876,7 +900,8 @@ static int sbefifo_user_release(struct inode *inode, struct file *file)
876900
if (!user)
877901
return -EINVAL;
878902

879-
free_page((unsigned long)user->pending_cmd);
903+
sbefifo_release_command(user);
904+
free_page((unsigned long)user->cmd_page);
880905
kfree(user);
881906

882907
return 0;

drivers/fsi/fsi-scom.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ static int scom_probe(struct device *dev)
598598
kfree(scom);
599599
return -ENODEV;
600600
}
601+
scom->fsi_dev = fsi_dev;
601602

602603
/* Create chardev for userspace access */
603604
scom->dev.type = &fsi_cdev_type;

0 commit comments

Comments
 (0)