diff options
author | Sean Young <sean@mess.org> | 2017-12-13 16:09:21 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-12-18 15:21:28 -0500 |
commit | a74b2bff59455d466a4422ee2f49151ffd65a2ab (patch) | |
tree | 7e440794300206a08e00bff023f6565f5ed2eb6b | |
parent | b996157dd2b9de57a61a6abbe4ab2d63e1d10908 (diff) |
media: lirc: do not pass ERR_PTR to kfree
If memdup_user() fails, txbuf will be an error pointer and passed
to kfree.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r-- | drivers/media/rc/lirc_dev.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 6cedb546c3e0..8618aba152c6 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c | |||
@@ -231,7 +231,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
231 | { | 231 | { |
232 | struct lirc_fh *fh = file->private_data; | 232 | struct lirc_fh *fh = file->private_data; |
233 | struct rc_dev *dev = fh->rc; | 233 | struct rc_dev *dev = fh->rc; |
234 | unsigned int *txbuf = NULL; | 234 | unsigned int *txbuf; |
235 | struct ir_raw_event *raw = NULL; | 235 | struct ir_raw_event *raw = NULL; |
236 | ssize_t ret; | 236 | ssize_t ret; |
237 | size_t count; | 237 | size_t count; |
@@ -246,14 +246,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
246 | 246 | ||
247 | if (!dev->registered) { | 247 | if (!dev->registered) { |
248 | ret = -ENODEV; | 248 | ret = -ENODEV; |
249 | goto out; | 249 | goto out_unlock; |
250 | } | 250 | } |
251 | 251 | ||
252 | start = ktime_get(); | 252 | start = ktime_get(); |
253 | 253 | ||
254 | if (!dev->tx_ir) { | 254 | if (!dev->tx_ir) { |
255 | ret = -EINVAL; | 255 | ret = -EINVAL; |
256 | goto out; | 256 | goto out_unlock; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (fh->send_mode == LIRC_MODE_SCANCODE) { | 259 | if (fh->send_mode == LIRC_MODE_SCANCODE) { |
@@ -261,17 +261,17 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
261 | 261 | ||
262 | if (n != sizeof(scan)) { | 262 | if (n != sizeof(scan)) { |
263 | ret = -EINVAL; | 263 | ret = -EINVAL; |
264 | goto out; | 264 | goto out_unlock; |
265 | } | 265 | } |
266 | 266 | ||
267 | if (copy_from_user(&scan, buf, sizeof(scan))) { | 267 | if (copy_from_user(&scan, buf, sizeof(scan))) { |
268 | ret = -EFAULT; | 268 | ret = -EFAULT; |
269 | goto out; | 269 | goto out_unlock; |
270 | } | 270 | } |
271 | 271 | ||
272 | if (scan.flags || scan.keycode || scan.timestamp) { | 272 | if (scan.flags || scan.keycode || scan.timestamp) { |
273 | ret = -EINVAL; | 273 | ret = -EINVAL; |
274 | goto out; | 274 | goto out_unlock; |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | 277 | /* |
@@ -283,26 +283,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
283 | if (scan.scancode > U32_MAX || | 283 | if (scan.scancode > U32_MAX || |
284 | !rc_validate_scancode(scan.rc_proto, scan.scancode)) { | 284 | !rc_validate_scancode(scan.rc_proto, scan.scancode)) { |
285 | ret = -EINVAL; | 285 | ret = -EINVAL; |
286 | goto out; | 286 | goto out_unlock; |
287 | } | 287 | } |
288 | 288 | ||
289 | raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL); | 289 | raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL); |
290 | if (!raw) { | 290 | if (!raw) { |
291 | ret = -ENOMEM; | 291 | ret = -ENOMEM; |
292 | goto out; | 292 | goto out_unlock; |
293 | } | 293 | } |
294 | 294 | ||
295 | ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode, | 295 | ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode, |
296 | raw, LIRCBUF_SIZE); | 296 | raw, LIRCBUF_SIZE); |
297 | if (ret < 0) | 297 | if (ret < 0) |
298 | goto out; | 298 | goto out_kfree; |
299 | 299 | ||
300 | count = ret; | 300 | count = ret; |
301 | 301 | ||
302 | txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL); | 302 | txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL); |
303 | if (!txbuf) { | 303 | if (!txbuf) { |
304 | ret = -ENOMEM; | 304 | ret = -ENOMEM; |
305 | goto out; | 305 | goto out_kfree; |
306 | } | 306 | } |
307 | 307 | ||
308 | for (i = 0; i < count; i++) | 308 | for (i = 0; i < count; i++) |
@@ -318,26 +318,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
318 | } else { | 318 | } else { |
319 | if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) { | 319 | if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) { |
320 | ret = -EINVAL; | 320 | ret = -EINVAL; |
321 | goto out; | 321 | goto out_unlock; |
322 | } | 322 | } |
323 | 323 | ||
324 | count = n / sizeof(unsigned int); | 324 | count = n / sizeof(unsigned int); |
325 | if (count > LIRCBUF_SIZE || count % 2 == 0) { | 325 | if (count > LIRCBUF_SIZE || count % 2 == 0) { |
326 | ret = -EINVAL; | 326 | ret = -EINVAL; |
327 | goto out; | 327 | goto out_unlock; |
328 | } | 328 | } |
329 | 329 | ||
330 | txbuf = memdup_user(buf, n); | 330 | txbuf = memdup_user(buf, n); |
331 | if (IS_ERR(txbuf)) { | 331 | if (IS_ERR(txbuf)) { |
332 | ret = PTR_ERR(txbuf); | 332 | ret = PTR_ERR(txbuf); |
333 | goto out; | 333 | goto out_unlock; |
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
337 | for (i = 0; i < count; i++) { | 337 | for (i = 0; i < count; i++) { |
338 | if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { | 338 | if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { |
339 | ret = -EINVAL; | 339 | ret = -EINVAL; |
340 | goto out; | 340 | goto out_kfree; |
341 | } | 341 | } |
342 | 342 | ||
343 | duration += txbuf[i]; | 343 | duration += txbuf[i]; |
@@ -345,7 +345,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
345 | 345 | ||
346 | ret = dev->tx_ir(dev, txbuf, count); | 346 | ret = dev->tx_ir(dev, txbuf, count); |
347 | if (ret < 0) | 347 | if (ret < 0) |
348 | goto out; | 348 | goto out_kfree; |
349 | 349 | ||
350 | if (fh->send_mode == LIRC_MODE_SCANCODE) { | 350 | if (fh->send_mode == LIRC_MODE_SCANCODE) { |
351 | ret = n; | 351 | ret = n; |
@@ -368,10 +368,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
368 | schedule_timeout(usecs_to_jiffies(towait)); | 368 | schedule_timeout(usecs_to_jiffies(towait)); |
369 | } | 369 | } |
370 | 370 | ||
371 | out: | 371 | out_kfree: |
372 | mutex_unlock(&dev->lock); | ||
373 | kfree(txbuf); | 372 | kfree(txbuf); |
374 | kfree(raw); | 373 | kfree(raw); |
374 | out_unlock: | ||
375 | mutex_unlock(&dev->lock); | ||
375 | return ret; | 376 | return ret; |
376 | } | 377 | } |
377 | 378 | ||