Loading drivers/misc/qfp_fuse.c +49 −34 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ /* * Time QFPROM requires to reliably burn a fuse. */ #define QFPROM_BLOW_TIMEOUT_US 10 #define QFPROM_BLOW_TIMEOUT_US 20 #define QFPROM_BLOW_TIMER_OFFSET 0x2038 /* * Denotes number of cycles required to blow the fuse. Loading @@ -42,6 +42,9 @@ #define QFP_FUSE_READY 0x01 #define QFP_FUSE_OFF 0x00 #define QFP_FUSE_BUF_SIZE 64 static const char *blow_supply = "vdd-blow"; struct qfp_priv_t { Loading @@ -63,6 +66,20 @@ struct qfp_resource { /* We need only one instance of this for the driver */ static struct qfp_priv_t *qfp_priv; static inline bool is_usr_req_valid(const struct qfp_fuse_req *req) { uint32_t size = qfp_priv->end - qfp_priv->base; uint32_t req_size = req->size * sizeof(uint32_t); if ((req_size == 0) || (req_size > size)) return false; if (req->offset >= size) return false; if ((req->offset + req_size) > size) return false; return true; } static int qfp_fuse_open(struct inode *inode, struct file *filp) { Loading Loading @@ -187,7 +204,9 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; struct qfp_fuse_req req; u32 *buf = NULL; u32 fuse_buf[QFP_FUSE_BUF_SIZE]; u32 *buf = fuse_buf; u32 *ptr = NULL; int i; /* Verify user arguments. */ Loading @@ -209,26 +228,22 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } /* Check for limits */ if (!req.size) { pr_err("Request size zero.\n"); err = -EFAULT; break; } if (qfp_priv->base + req.offset + (req.size - 1) * 4 > qfp_priv->end) { pr_err("Req size exceeds QFPROM addr space\n"); err = -EFAULT; if (is_usr_req_valid(&req) == false) { pr_err("Invalid request\n"); err = -EINVAL; break; } if (req.size > QFP_FUSE_BUF_SIZE) { /* Allocate memory for buffer */ buf = kzalloc(req.size * 4, GFP_KERNEL); if (buf == NULL) { ptr = kzalloc(req.size * 4, GFP_KERNEL); if (ptr == NULL) { pr_alert("No memory for data\n"); err = -ENOMEM; break; } buf = ptr; } if (mutex_lock_interruptible(&qfp_priv->lock)) { err = -ERESTARTSYS; Loading Loading @@ -260,26 +275,24 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = -EFAULT; break; } /* Check for limits */ if (!req.size) { pr_err("Request size zero.\n"); err = -EFAULT; break; } if (qfp_priv->base + req.offset + (req.size - 1) * 4 > qfp_priv->end) { pr_err("Req size exceeds QFPROM space\n"); err = -EFAULT; if (is_usr_req_valid(&req) == false) { pr_err("Invalid request\n"); err = -EINVAL; break; } if (req.size > QFP_FUSE_BUF_SIZE) { /* Allocate memory for buffer */ buf = kzalloc(4 * (req.size), GFP_KERNEL); if (buf == NULL) { ptr = kzalloc(req.size * 4, GFP_KERNEL); if (ptr == NULL) { pr_alert("No memory for data\n"); err = -ENOMEM; break; } buf = ptr; } /* Copy user data to local buffer */ if (copy_from_user(buf, (void __user *)req.data, Loading @@ -306,7 +319,9 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) pr_err("Invalid ioctl command.\n"); return -ENOTTY; } kfree(buf); kfree(ptr); return err; } Loading Loading
drivers/misc/qfp_fuse.c +49 −34 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ /* * Time QFPROM requires to reliably burn a fuse. */ #define QFPROM_BLOW_TIMEOUT_US 10 #define QFPROM_BLOW_TIMEOUT_US 20 #define QFPROM_BLOW_TIMER_OFFSET 0x2038 /* * Denotes number of cycles required to blow the fuse. Loading @@ -42,6 +42,9 @@ #define QFP_FUSE_READY 0x01 #define QFP_FUSE_OFF 0x00 #define QFP_FUSE_BUF_SIZE 64 static const char *blow_supply = "vdd-blow"; struct qfp_priv_t { Loading @@ -63,6 +66,20 @@ struct qfp_resource { /* We need only one instance of this for the driver */ static struct qfp_priv_t *qfp_priv; static inline bool is_usr_req_valid(const struct qfp_fuse_req *req) { uint32_t size = qfp_priv->end - qfp_priv->base; uint32_t req_size = req->size * sizeof(uint32_t); if ((req_size == 0) || (req_size > size)) return false; if (req->offset >= size) return false; if ((req->offset + req_size) > size) return false; return true; } static int qfp_fuse_open(struct inode *inode, struct file *filp) { Loading Loading @@ -187,7 +204,9 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; struct qfp_fuse_req req; u32 *buf = NULL; u32 fuse_buf[QFP_FUSE_BUF_SIZE]; u32 *buf = fuse_buf; u32 *ptr = NULL; int i; /* Verify user arguments. */ Loading @@ -209,26 +228,22 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } /* Check for limits */ if (!req.size) { pr_err("Request size zero.\n"); err = -EFAULT; break; } if (qfp_priv->base + req.offset + (req.size - 1) * 4 > qfp_priv->end) { pr_err("Req size exceeds QFPROM addr space\n"); err = -EFAULT; if (is_usr_req_valid(&req) == false) { pr_err("Invalid request\n"); err = -EINVAL; break; } if (req.size > QFP_FUSE_BUF_SIZE) { /* Allocate memory for buffer */ buf = kzalloc(req.size * 4, GFP_KERNEL); if (buf == NULL) { ptr = kzalloc(req.size * 4, GFP_KERNEL); if (ptr == NULL) { pr_alert("No memory for data\n"); err = -ENOMEM; break; } buf = ptr; } if (mutex_lock_interruptible(&qfp_priv->lock)) { err = -ERESTARTSYS; Loading Loading @@ -260,26 +275,24 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = -EFAULT; break; } /* Check for limits */ if (!req.size) { pr_err("Request size zero.\n"); err = -EFAULT; break; } if (qfp_priv->base + req.offset + (req.size - 1) * 4 > qfp_priv->end) { pr_err("Req size exceeds QFPROM space\n"); err = -EFAULT; if (is_usr_req_valid(&req) == false) { pr_err("Invalid request\n"); err = -EINVAL; break; } if (req.size > QFP_FUSE_BUF_SIZE) { /* Allocate memory for buffer */ buf = kzalloc(4 * (req.size), GFP_KERNEL); if (buf == NULL) { ptr = kzalloc(req.size * 4, GFP_KERNEL); if (ptr == NULL) { pr_alert("No memory for data\n"); err = -ENOMEM; break; } buf = ptr; } /* Copy user data to local buffer */ if (copy_from_user(buf, (void __user *)req.data, Loading @@ -306,7 +319,9 @@ qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) pr_err("Invalid ioctl command.\n"); return -ENOTTY; } kfree(buf); kfree(ptr); return err; } Loading