diff options
author | Devin Heitmueller <dheitmueller@kernellabs.com> | 2012-08-06 21:47:07 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-11 11:37:55 -0400 |
commit | 77fc286328e6fd9a80ef8ce6963db7fbf4e07a1a (patch) | |
tree | b7b320eadf82fd8649790a2791f37a1273661307 | |
parent | 1240ad56edfdd9ccc70d9cbce6da7d5d939d5e83 (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.c | 40 |
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 | ||
57 | u32 au0828_readreg(struct au0828_dev *dev, u16 reg) | 57 | u32 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 | ||
64 | u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) | 67 | u32 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 | ||
70 | static 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 | |||
88 | static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, | 73 | static 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; |