Loading drivers/char/ipmi/ipmi_devintf.c +115 −133 Original line number Diff line number Diff line Loading @@ -231,63 +231,16 @@ static int handle_send_req(ipmi_user_t user, return rv; } static int ipmi_ioctl(struct file *file, unsigned int cmd, unsigned long data) { int rv = -EINVAL; struct ipmi_file_private *priv = file->private_data; void __user *arg = (void __user *)data; switch (cmd) static int handle_recv(struct ipmi_file_private *priv, bool trunc, struct ipmi_recv *rsp, int (*copyout)(struct ipmi_recv *, void __user *), void __user *to) { case IPMICTL_SEND_COMMAND: { struct ipmi_req req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req, priv->default_retries, priv->default_retry_time_ms); break; } case IPMICTL_SEND_COMMAND_SETTIME: { struct ipmi_req_settime req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req.req, req.retries, req.retry_time_ms); break; } case IPMICTL_RECEIVE_MSG: case IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv rsp; int addr_len; struct list_head *entry; struct ipmi_recv_msg *msg; unsigned long flags; rv = 0; if (copy_from_user(&rsp, arg, sizeof(rsp))) { rv = -EFAULT; break; } int rv = 0; /* We claim a mutex because we don't want two users getting something from the queue at a time. Loading @@ -312,53 +265,51 @@ static int ipmi_ioctl(struct file *file, spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); addr_len = ipmi_addr_length(msg->addr.addr_type); if (rsp.addr_len < addr_len) if (rsp->addr_len < addr_len) { rv = -EINVAL; goto recv_putback_on_err; } if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) { if (copy_to_user(rsp->addr, &(msg->addr), addr_len)) { rv = -EFAULT; goto recv_putback_on_err; } rsp.addr_len = addr_len; rsp->addr_len = addr_len; rsp.recv_type = msg->recv_type; rsp.msgid = msg->msgid; rsp.msg.netfn = msg->msg.netfn; rsp.msg.cmd = msg->msg.cmd; rsp->recv_type = msg->recv_type; rsp->msgid = msg->msgid; rsp->msg.netfn = msg->msg.netfn; rsp->msg.cmd = msg->msg.cmd; if (msg->msg.data_len > 0) { if (rsp.msg.data_len < msg->msg.data_len) { if (rsp->msg.data_len < msg->msg.data_len) { rv = -EMSGSIZE; if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) { msg->msg.data_len = rsp.msg.data_len; } else { if (trunc) msg->msg.data_len = rsp->msg.data_len; else goto recv_putback_on_err; } } if (copy_to_user(rsp.msg.data, if (copy_to_user(rsp->msg.data, msg->msg.data, msg->msg.data_len)) { rv = -EFAULT; goto recv_putback_on_err; } rsp.msg.data_len = msg->msg.data_len; rsp->msg.data_len = msg->msg.data_len; } else { rsp.msg.data_len = 0; rsp->msg.data_len = 0; } if (copy_to_user(arg, &rsp, sizeof(rsp))) { rv = -EFAULT; rv = copyout(rsp, to); if (rv) goto recv_putback_on_err; } mutex_unlock(&priv->recv_mutex); ipmi_free_recv_msg(msg); break; return 0; recv_putback_on_err: /* If we got an error, put the message back onto Loading @@ -366,11 +317,68 @@ static int ipmi_ioctl(struct file *file, spin_lock_irqsave(&(priv->recv_msg_lock), flags); list_add(entry, &(priv->recv_msgs)); spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); recv_err: mutex_unlock(&priv->recv_mutex); return rv; } static int copyout_recv(struct ipmi_recv *rsp, void __user *to) { return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0; } static int ipmi_ioctl(struct file *file, unsigned int cmd, unsigned long data) { int rv = -EINVAL; struct ipmi_file_private *priv = file->private_data; void __user *arg = (void __user *)data; switch (cmd) { case IPMICTL_SEND_COMMAND: { struct ipmi_req req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } recv_err: mutex_unlock(&priv->recv_mutex); rv = handle_send_req(priv->user, &req, priv->default_retries, priv->default_retry_time_ms); break; } case IPMICTL_SEND_COMMAND_SETTIME: { struct ipmi_req_settime req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req.req, req.retries, req.retry_time_ms); break; } case IPMICTL_RECEIVE_MSG: case IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv rsp; if (copy_from_user(&rsp, arg, sizeof(rsp))) rv = -EFAULT; else rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC, &rsp, copyout_recv, arg); break; } Loading Loading @@ -711,17 +719,6 @@ static long get_compat_ipmi_msg(struct ipmi_msg *p64, return 0; } static long put_compat_ipmi_msg(struct ipmi_msg *p64, struct compat_ipmi_msg __user *p32) { if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || __put_user(p64->netfn, &p32->netfn) || __put_user(p64->cmd, &p32->cmd) || __put_user(p64->data_len, &p32->data_len)) return -EFAULT; return 0; } static long get_compat_ipmi_req(struct ipmi_req *p64, struct compat_ipmi_req __user *p32) { Loading Loading @@ -765,16 +762,19 @@ static long get_compat_ipmi_recv(struct ipmi_recv *p64, return 0; } static long put_compat_ipmi_recv(struct ipmi_recv *p64, struct compat_ipmi_recv __user *p32) static int copyout_recv32(struct ipmi_recv *p64, void __user *to) { if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || __put_user(p64->recv_type, &p32->recv_type) || __put_user(p64->addr_len, &p32->addr_len) || __put_user(p64->msgid, &p32->msgid) || put_compat_ipmi_msg(&p64->msg, &p32->msg)) return -EFAULT; return 0; struct compat_ipmi_recv v32; memset(&v32, 0, sizeof(struct compat_ipmi_recv)); v32.recv_type = p64->recv_type; v32.addr = ptr_to_compat(p64->addr); v32.addr_len = p64->addr_len; v32.msgid = p64->msgid; v32.msg.netfn = p64->msg.netfn; v32.msg.cmd = p64->msg.cmd; v32.msg.data_len = p64->msg.data_len; v32.msg.data = ptr_to_compat(p64->msg.data); return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0; } /* Loading @@ -783,7 +783,6 @@ static long put_compat_ipmi_recv(struct ipmi_recv *p64, static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int rc; struct ipmi_file_private *priv = filep->private_data; switch(cmd) { Loading Loading @@ -811,32 +810,15 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, case COMPAT_IPMICTL_RECEIVE_MSG: case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv __user *precv64; struct ipmi_recv recv64; memset(&recv64, 0, sizeof(recv64)); if (get_compat_ipmi_recv(&recv64, compat_ptr(arg))) return -EFAULT; precv64 = compat_alloc_user_space(sizeof(recv64)); if (copy_to_user(precv64, &recv64, sizeof(recv64))) return -EFAULT; rc = ipmi_ioctl(filep, ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) ? IPMICTL_RECEIVE_MSG : IPMICTL_RECEIVE_MSG_TRUNC), (unsigned long) precv64); if (rc != 0) return rc; if (copy_from_user(&recv64, precv64, sizeof(recv64))) return -EFAULT; if (put_compat_ipmi_recv(&recv64, compat_ptr(arg))) return -EFAULT; return rc; return handle_recv(priv, cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC, &recv64, copyout_recv32, compat_ptr(arg)); } default: return ipmi_ioctl(filep, cmd, arg); Loading Loading
drivers/char/ipmi/ipmi_devintf.c +115 −133 Original line number Diff line number Diff line Loading @@ -231,63 +231,16 @@ static int handle_send_req(ipmi_user_t user, return rv; } static int ipmi_ioctl(struct file *file, unsigned int cmd, unsigned long data) { int rv = -EINVAL; struct ipmi_file_private *priv = file->private_data; void __user *arg = (void __user *)data; switch (cmd) static int handle_recv(struct ipmi_file_private *priv, bool trunc, struct ipmi_recv *rsp, int (*copyout)(struct ipmi_recv *, void __user *), void __user *to) { case IPMICTL_SEND_COMMAND: { struct ipmi_req req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req, priv->default_retries, priv->default_retry_time_ms); break; } case IPMICTL_SEND_COMMAND_SETTIME: { struct ipmi_req_settime req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req.req, req.retries, req.retry_time_ms); break; } case IPMICTL_RECEIVE_MSG: case IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv rsp; int addr_len; struct list_head *entry; struct ipmi_recv_msg *msg; unsigned long flags; rv = 0; if (copy_from_user(&rsp, arg, sizeof(rsp))) { rv = -EFAULT; break; } int rv = 0; /* We claim a mutex because we don't want two users getting something from the queue at a time. Loading @@ -312,53 +265,51 @@ static int ipmi_ioctl(struct file *file, spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); addr_len = ipmi_addr_length(msg->addr.addr_type); if (rsp.addr_len < addr_len) if (rsp->addr_len < addr_len) { rv = -EINVAL; goto recv_putback_on_err; } if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) { if (copy_to_user(rsp->addr, &(msg->addr), addr_len)) { rv = -EFAULT; goto recv_putback_on_err; } rsp.addr_len = addr_len; rsp->addr_len = addr_len; rsp.recv_type = msg->recv_type; rsp.msgid = msg->msgid; rsp.msg.netfn = msg->msg.netfn; rsp.msg.cmd = msg->msg.cmd; rsp->recv_type = msg->recv_type; rsp->msgid = msg->msgid; rsp->msg.netfn = msg->msg.netfn; rsp->msg.cmd = msg->msg.cmd; if (msg->msg.data_len > 0) { if (rsp.msg.data_len < msg->msg.data_len) { if (rsp->msg.data_len < msg->msg.data_len) { rv = -EMSGSIZE; if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) { msg->msg.data_len = rsp.msg.data_len; } else { if (trunc) msg->msg.data_len = rsp->msg.data_len; else goto recv_putback_on_err; } } if (copy_to_user(rsp.msg.data, if (copy_to_user(rsp->msg.data, msg->msg.data, msg->msg.data_len)) { rv = -EFAULT; goto recv_putback_on_err; } rsp.msg.data_len = msg->msg.data_len; rsp->msg.data_len = msg->msg.data_len; } else { rsp.msg.data_len = 0; rsp->msg.data_len = 0; } if (copy_to_user(arg, &rsp, sizeof(rsp))) { rv = -EFAULT; rv = copyout(rsp, to); if (rv) goto recv_putback_on_err; } mutex_unlock(&priv->recv_mutex); ipmi_free_recv_msg(msg); break; return 0; recv_putback_on_err: /* If we got an error, put the message back onto Loading @@ -366,11 +317,68 @@ static int ipmi_ioctl(struct file *file, spin_lock_irqsave(&(priv->recv_msg_lock), flags); list_add(entry, &(priv->recv_msgs)); spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); recv_err: mutex_unlock(&priv->recv_mutex); return rv; } static int copyout_recv(struct ipmi_recv *rsp, void __user *to) { return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0; } static int ipmi_ioctl(struct file *file, unsigned int cmd, unsigned long data) { int rv = -EINVAL; struct ipmi_file_private *priv = file->private_data; void __user *arg = (void __user *)data; switch (cmd) { case IPMICTL_SEND_COMMAND: { struct ipmi_req req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } recv_err: mutex_unlock(&priv->recv_mutex); rv = handle_send_req(priv->user, &req, priv->default_retries, priv->default_retry_time_ms); break; } case IPMICTL_SEND_COMMAND_SETTIME: { struct ipmi_req_settime req; if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } rv = handle_send_req(priv->user, &req.req, req.retries, req.retry_time_ms); break; } case IPMICTL_RECEIVE_MSG: case IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv rsp; if (copy_from_user(&rsp, arg, sizeof(rsp))) rv = -EFAULT; else rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC, &rsp, copyout_recv, arg); break; } Loading Loading @@ -711,17 +719,6 @@ static long get_compat_ipmi_msg(struct ipmi_msg *p64, return 0; } static long put_compat_ipmi_msg(struct ipmi_msg *p64, struct compat_ipmi_msg __user *p32) { if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || __put_user(p64->netfn, &p32->netfn) || __put_user(p64->cmd, &p32->cmd) || __put_user(p64->data_len, &p32->data_len)) return -EFAULT; return 0; } static long get_compat_ipmi_req(struct ipmi_req *p64, struct compat_ipmi_req __user *p32) { Loading Loading @@ -765,16 +762,19 @@ static long get_compat_ipmi_recv(struct ipmi_recv *p64, return 0; } static long put_compat_ipmi_recv(struct ipmi_recv *p64, struct compat_ipmi_recv __user *p32) static int copyout_recv32(struct ipmi_recv *p64, void __user *to) { if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || __put_user(p64->recv_type, &p32->recv_type) || __put_user(p64->addr_len, &p32->addr_len) || __put_user(p64->msgid, &p32->msgid) || put_compat_ipmi_msg(&p64->msg, &p32->msg)) return -EFAULT; return 0; struct compat_ipmi_recv v32; memset(&v32, 0, sizeof(struct compat_ipmi_recv)); v32.recv_type = p64->recv_type; v32.addr = ptr_to_compat(p64->addr); v32.addr_len = p64->addr_len; v32.msgid = p64->msgid; v32.msg.netfn = p64->msg.netfn; v32.msg.cmd = p64->msg.cmd; v32.msg.data_len = p64->msg.data_len; v32.msg.data = ptr_to_compat(p64->msg.data); return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0; } /* Loading @@ -783,7 +783,6 @@ static long put_compat_ipmi_recv(struct ipmi_recv *p64, static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int rc; struct ipmi_file_private *priv = filep->private_data; switch(cmd) { Loading Loading @@ -811,32 +810,15 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, case COMPAT_IPMICTL_RECEIVE_MSG: case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC: { struct ipmi_recv __user *precv64; struct ipmi_recv recv64; memset(&recv64, 0, sizeof(recv64)); if (get_compat_ipmi_recv(&recv64, compat_ptr(arg))) return -EFAULT; precv64 = compat_alloc_user_space(sizeof(recv64)); if (copy_to_user(precv64, &recv64, sizeof(recv64))) return -EFAULT; rc = ipmi_ioctl(filep, ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) ? IPMICTL_RECEIVE_MSG : IPMICTL_RECEIVE_MSG_TRUNC), (unsigned long) precv64); if (rc != 0) return rc; if (copy_from_user(&recv64, precv64, sizeof(recv64))) return -EFAULT; if (put_compat_ipmi_recv(&recv64, compat_ptr(arg))) return -EFAULT; return rc; return handle_recv(priv, cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC, &recv64, copyout_recv32, compat_ptr(arg)); } default: return ipmi_ioctl(filep, cmd, arg); Loading