aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2012-08-06 21:47:07 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-11 11:37:55 -0400
commit77fc286328e6fd9a80ef8ce6963db7fbf4e07a1a (patch)
treeb7b320eadf82fd8649790a2791f37a1273661307
parent1240ad56edfdd9ccc70d9cbce6da7d5d939d5e83 (diff)
[media] au0828: fix possible race condition in usage of dev->ctrlmsg
The register read function is referencing the dev->ctrlmsg structure outside of the dev->mutex lock, which can cause corruption of the value if multiple callers are invoking au0828_readreg() simultaneously. Use a stack variable to hold the result, and copy the buffer returned by usb_control_msg() to that variable. In reality, the whole recv_control_msg() function can probably be collapsed into au0288_readreg() since it is the only caller. Also get rid of cmd_msg_dump() since the only case in which the function is ever called only is ever passed a single byte for the response (and it is already logged). Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/au0828/au0828-core.c40
1 files changed, 12 insertions, 28 deletions
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index 65914bc421d0..745a80a798c8 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -56,9 +56,12 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
56 56
57u32 au0828_readreg(struct au0828_dev *dev, u16 reg) 57u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
58{ 58{
59 recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); 59 u8 result = 0;
60 dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]); 60
61 return dev->ctrlmsg[0]; 61 recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
62 dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
63
64 return result;
62} 65}
63 66
64u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) 67u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
@@ -67,24 +70,6 @@ u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
67 return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); 70 return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
68} 71}
69 72
70static void cmd_msg_dump(struct au0828_dev *dev)
71{
72 int i;
73
74 for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
75 dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
76 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
77 __func__,
78 dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
79 dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
80 dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
81 dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
82 dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
83 dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
84 dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
85 dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
86}
87
88static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, 73static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
89 u16 index) 74 u16 index)
90{ 75{
@@ -118,24 +103,23 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
118 int status = -ENODEV; 103 int status = -ENODEV;
119 mutex_lock(&dev->mutex); 104 mutex_lock(&dev->mutex);
120 if (dev->usbdev) { 105 if (dev->usbdev) {
121
122 memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
123
124 /* cp must be memory that has been allocated by kmalloc */
125 status = usb_control_msg(dev->usbdev, 106 status = usb_control_msg(dev->usbdev,
126 usb_rcvctrlpipe(dev->usbdev, 0), 107 usb_rcvctrlpipe(dev->usbdev, 0),
127 request, 108 request,
128 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 109 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
129 value, index, 110 value, index,
130 cp, size, 1000); 111 dev->ctrlmsg, size, 1000);
131 112
132 status = min(status, 0); 113 status = min(status, 0);
133 114
134 if (status < 0) { 115 if (status < 0) {
135 printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", 116 printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
136 __func__, status); 117 __func__, status);
137 } else 118 }
138 cmd_msg_dump(dev); 119
120 /* the host controller requires heap allocated memory, which
121 is why we didn't just pass "cp" into usb_control_msg */
122 memcpy(cp, dev->ctrlmsg, size);
139 } 123 }
140 mutex_unlock(&dev->mutex); 124 mutex_unlock(&dev->mutex);
141 return status; 125 return status;