[ The copy_to_user() overflow code is weird.  Why do we need to do a
  atomic_read()?  That suggests that there is a potential time of check
  time of use bug where we do:

        if (atomic_read(&gcdev->watch_abi_version) == 2) // <<-- time of check
                event_size = sizeof(struct gpioline_info_changed_v2);

        ...

        if (atomic_read(&gcdev->watch_abi_version) == 2) { // <<-- time of use
                copy_to_user(blah, blah, event_size);

  If the value for "gcdev->watch_abi_version" changes between the time
  of check and the time of use then it can read beyond the end of the
  buffer.

  -- dan ]

Hi Kent,

Thank you for the patch! Perhaps something to improve:

url:    
https://github.com/0day-ci/linux/commits/Kent-Gibson/gpio-cdev-add-uAPI-V2/20200623-120634
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git 
for-next
config: openrisc-randconfig-m031-20200623 (attached as .config)
compiler: or1k-linux-gcc (GCC) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>

smatch warnings:
drivers/gpio/gpiolib-cdev.c:891 line_free() error: dereferencing freed memory 
'line'
drivers/gpio/gpiolib-cdev.c:949 line_create() warn: possible memory leak of 
'line'
drivers/gpio/gpiolib-cdev.c:1860 lineinfo_watch_read() error: copy_to_user() 
'&event_v1' too small (104 vs 168)

# 
https://github.com/0day-ci/linux/commit/f3b3ae8752adc5ac33dcf83d49b0b02f2d7ef43b
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout f3b3ae8752adc5ac33dcf83d49b0b02f2d7ef43b
vim +/line +891 drivers/gpio/gpiolib-cdev.c

f3b3ae8752adc5 Kent Gibson 2020-06-23   877  static void line_free(struct line 
*line)
f3b3ae8752adc5 Kent Gibson 2020-06-23   878  {
f3b3ae8752adc5 Kent Gibson 2020-06-23   879     int i;
f3b3ae8752adc5 Kent Gibson 2020-06-23   880  
f3b3ae8752adc5 Kent Gibson 2020-06-23   881     for (i = 0; i < 
line->num_descs; i++) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   882             if (line->edets)
f3b3ae8752adc5 Kent Gibson 2020-06-23   883                     
edge_detector_stop(&line->edets[i]);
f3b3ae8752adc5 Kent Gibson 2020-06-23   884             if (line->descs[i])
f3b3ae8752adc5 Kent Gibson 2020-06-23   885                     
gpiod_free(line->descs[i]);
f3b3ae8752adc5 Kent Gibson 2020-06-23   886     }
f3b3ae8752adc5 Kent Gibson 2020-06-23   887     kfifo_free(&line->events);
f3b3ae8752adc5 Kent Gibson 2020-06-23   888     kfree(line->label);
f3b3ae8752adc5 Kent Gibson 2020-06-23   889     kfree(line->edets);
f3b3ae8752adc5 Kent Gibson 2020-06-23   890     kfree(line);
f3b3ae8752adc5 Kent Gibson 2020-06-23  @891     put_device(&line->gdev->dev);
f3b3ae8752adc5 Kent Gibson 2020-06-23   892  }
f3b3ae8752adc5 Kent Gibson 2020-06-23   893  
f3b3ae8752adc5 Kent Gibson 2020-06-23   894  static int line_release(struct 
inode *inode, struct file *file)
f3b3ae8752adc5 Kent Gibson 2020-06-23   895  {
f3b3ae8752adc5 Kent Gibson 2020-06-23   896     struct line *line = 
file->private_data;
f3b3ae8752adc5 Kent Gibson 2020-06-23   897  
f3b3ae8752adc5 Kent Gibson 2020-06-23   898     line_free(line);
f3b3ae8752adc5 Kent Gibson 2020-06-23   899     return 0;
f3b3ae8752adc5 Kent Gibson 2020-06-23   900  }
f3b3ae8752adc5 Kent Gibson 2020-06-23   901  
f3b3ae8752adc5 Kent Gibson 2020-06-23   902  static const struct 
file_operations line_fileops = {
f3b3ae8752adc5 Kent Gibson 2020-06-23   903     .release = line_release,
f3b3ae8752adc5 Kent Gibson 2020-06-23   904     .read = line_read,
f3b3ae8752adc5 Kent Gibson 2020-06-23   905     .poll = line_poll,
f3b3ae8752adc5 Kent Gibson 2020-06-23   906     .owner = THIS_MODULE,
f3b3ae8752adc5 Kent Gibson 2020-06-23   907     .llseek = noop_llseek,
f3b3ae8752adc5 Kent Gibson 2020-06-23   908     .unlocked_ioctl = line_ioctl,
f3b3ae8752adc5 Kent Gibson 2020-06-23   909  #ifdef CONFIG_COMPAT
f3b3ae8752adc5 Kent Gibson 2020-06-23   910     .compat_ioctl = 
line_ioctl_compat,
f3b3ae8752adc5 Kent Gibson 2020-06-23   911  #endif
f3b3ae8752adc5 Kent Gibson 2020-06-23   912  };
f3b3ae8752adc5 Kent Gibson 2020-06-23   913  
f3b3ae8752adc5 Kent Gibson 2020-06-23   914  static int line_create(struct 
gpio_device *gdev, void __user *ip)
f3b3ae8752adc5 Kent Gibson 2020-06-23   915  {
f3b3ae8752adc5 Kent Gibson 2020-06-23   916     struct gpioline_request linereq;
f3b3ae8752adc5 Kent Gibson 2020-06-23   917     struct line *line;
f3b3ae8752adc5 Kent Gibson 2020-06-23   918     struct file *file;
f3b3ae8752adc5 Kent Gibson 2020-06-23   919     int fd, i, ret, size;
f3b3ae8752adc5 Kent Gibson 2020-06-23   920     struct gpioline_config *lc;
f3b3ae8752adc5 Kent Gibson 2020-06-23   921     unsigned long *vals;
f3b3ae8752adc5 Kent Gibson 2020-06-23   922  
f3b3ae8752adc5 Kent Gibson 2020-06-23   923     if (copy_from_user(&linereq, 
ip, sizeof(linereq)))
f3b3ae8752adc5 Kent Gibson 2020-06-23   924             return -EFAULT;
f3b3ae8752adc5 Kent Gibson 2020-06-23   925     if ((linereq.num_lines == 0) || 
(linereq.num_lines > GPIOLINES_MAX))
f3b3ae8752adc5 Kent Gibson 2020-06-23   926             return -EINVAL;
f3b3ae8752adc5 Kent Gibson 2020-06-23   927  
f3b3ae8752adc5 Kent Gibson 2020-06-23   928     if 
(padding_not_zeroed(linereq.padding, GPIOLINE_REQUEST_PAD_SIZE))
f3b3ae8752adc5 Kent Gibson 2020-06-23   929             return -EINVAL;
f3b3ae8752adc5 Kent Gibson 2020-06-23   930  
f3b3ae8752adc5 Kent Gibson 2020-06-23   931     lc = &linereq.config;
f3b3ae8752adc5 Kent Gibson 2020-06-23   932     ret = 
gpioline_config_validate(lc);
f3b3ae8752adc5 Kent Gibson 2020-06-23   933     if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23   934             return ret;
f3b3ae8752adc5 Kent Gibson 2020-06-23   935  
f3b3ae8752adc5 Kent Gibson 2020-06-23   936     /* event_buffer_size only valid 
with edge_detection */
f3b3ae8752adc5 Kent Gibson 2020-06-23   937     if ((linereq.event_buffer_size) 
&&
f3b3ae8752adc5 Kent Gibson 2020-06-23   938         !(linereq.config.flags & 
GPIOLINE_FLAG_V2_EDGE_DETECTION))
f3b3ae8752adc5 Kent Gibson 2020-06-23   939             return -EINVAL;
f3b3ae8752adc5 Kent Gibson 2020-06-23   940  
f3b3ae8752adc5 Kent Gibson 2020-06-23   941     line = 
kzalloc(struct_size(line, descs, linereq.num_lines),
f3b3ae8752adc5 Kent Gibson 2020-06-23   942                    GFP_KERNEL);
f3b3ae8752adc5 Kent Gibson 2020-06-23   943     if (!line)
f3b3ae8752adc5 Kent Gibson 2020-06-23   944             return -ENOMEM;
f3b3ae8752adc5 Kent Gibson 2020-06-23   945  
f3b3ae8752adc5 Kent Gibson 2020-06-23   946     line->edets = 
kcalloc(linereq.num_lines, sizeof(*line->edets),
f3b3ae8752adc5 Kent Gibson 2020-06-23   947                           
GFP_KERNEL);
f3b3ae8752adc5 Kent Gibson 2020-06-23   948     if (!line->edets)
f3b3ae8752adc5 Kent Gibson 2020-06-23  @949             return -ENOMEM;
                                                        ^^^^^^^^^^^^^^^
kfree(line) before returning.

f3b3ae8752adc5 Kent Gibson 2020-06-23   950  
f3b3ae8752adc5 Kent Gibson 2020-06-23   951     for (i = 0; i < 
linereq.num_lines; i++)
f3b3ae8752adc5 Kent Gibson 2020-06-23   952             line->edets[i].line = 
line;
f3b3ae8752adc5 Kent Gibson 2020-06-23   953  
f3b3ae8752adc5 Kent Gibson 2020-06-23   954     line->gdev = gdev;
f3b3ae8752adc5 Kent Gibson 2020-06-23   955     get_device(&gdev->dev);
f3b3ae8752adc5 Kent Gibson 2020-06-23   956  
f3b3ae8752adc5 Kent Gibson 2020-06-23   957     /* Make sure this is terminated 
*/
f3b3ae8752adc5 Kent Gibson 2020-06-23   958     
linereq.consumer[sizeof(linereq.consumer)-1] = '\0';
f3b3ae8752adc5 Kent Gibson 2020-06-23   959     if (strlen(linereq.consumer)) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   960             line->label = 
kstrdup(linereq.consumer, GFP_KERNEL);
f3b3ae8752adc5 Kent Gibson 2020-06-23   961             if (!line->label) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   962                     ret = -ENOMEM;
f3b3ae8752adc5 Kent Gibson 2020-06-23   963                     goto 
out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23   964             }
f3b3ae8752adc5 Kent Gibson 2020-06-23   965     }
f3b3ae8752adc5 Kent Gibson 2020-06-23   966  
f3b3ae8752adc5 Kent Gibson 2020-06-23   967     mutex_init(&line->config_mutex);
f3b3ae8752adc5 Kent Gibson 2020-06-23   968     
init_waitqueue_head(&line->wait);
f3b3ae8752adc5 Kent Gibson 2020-06-23   969     if (lc->edge_detection) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   970             size = 
linereq.event_buffer_size;
f3b3ae8752adc5 Kent Gibson 2020-06-23   971  
f3b3ae8752adc5 Kent Gibson 2020-06-23   972             if (size > 
GPIOLINES_MAX*16)
f3b3ae8752adc5 Kent Gibson 2020-06-23   973                     size = 
GPIOLINES_MAX*16;
f3b3ae8752adc5 Kent Gibson 2020-06-23   974             else if (size == 0)
f3b3ae8752adc5 Kent Gibson 2020-06-23   975                     size = 
linereq.num_lines*16;
f3b3ae8752adc5 Kent Gibson 2020-06-23   976  
f3b3ae8752adc5 Kent Gibson 2020-06-23   977             ret = 
kfifo_alloc(&line->events, size, GFP_KERNEL);
f3b3ae8752adc5 Kent Gibson 2020-06-23   978             if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23   979                     goto 
out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23   980  
f3b3ae8752adc5 Kent Gibson 2020-06-23   981             line->edge_detection = 
lc->edge_detection;
f3b3ae8752adc5 Kent Gibson 2020-06-23   982     }
f3b3ae8752adc5 Kent Gibson 2020-06-23   983  
f3b3ae8752adc5 Kent Gibson 2020-06-23   984     atomic_set(&line->seqno, 0);
f3b3ae8752adc5 Kent Gibson 2020-06-23   985     line->num_descs = 
linereq.num_lines;
f3b3ae8752adc5 Kent Gibson 2020-06-23   986     vals = (unsigned long 
*)lc->values.bitmap;
f3b3ae8752adc5 Kent Gibson 2020-06-23   987  
f3b3ae8752adc5 Kent Gibson 2020-06-23   988     /* Request each GPIO */
f3b3ae8752adc5 Kent Gibson 2020-06-23   989     for (i = 0; i < 
linereq.num_lines; i++) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   990             u32 offset = 
linereq.offsets[i];
f3b3ae8752adc5 Kent Gibson 2020-06-23   991             struct gpio_desc *desc 
= gpiochip_get_desc(gdev->chip, offset);
f3b3ae8752adc5 Kent Gibson 2020-06-23   992  
f3b3ae8752adc5 Kent Gibson 2020-06-23   993             if (IS_ERR(desc)) {
f3b3ae8752adc5 Kent Gibson 2020-06-23   994                     ret = 
PTR_ERR(desc);
f3b3ae8752adc5 Kent Gibson 2020-06-23   995                     goto 
out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23   996             }
f3b3ae8752adc5 Kent Gibson 2020-06-23   997  
f3b3ae8752adc5 Kent Gibson 2020-06-23   998             ret = 
gpiod_request(desc, line->label);
f3b3ae8752adc5 Kent Gibson 2020-06-23   999             if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23  1000                     goto 
out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1001  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1002             line->descs[i] = desc;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1003             
gpioline_config_to_desc_flags(lc, &desc->flags);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1004  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1005             ret = 
gpiod_set_transitory(desc, false);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1006             if (ret < 0)
f3b3ae8752adc5 Kent Gibson 2020-06-23  1007                     goto 
out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1008  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1009             /*
f3b3ae8752adc5 Kent Gibson 2020-06-23  1010              * Lines have to be 
requested explicitly for input
f3b3ae8752adc5 Kent Gibson 2020-06-23  1011              * or output, else the 
line will be treated "as is".
f3b3ae8752adc5 Kent Gibson 2020-06-23  1012              */
f3b3ae8752adc5 Kent Gibson 2020-06-23  1013             if (lc->flags & 
GPIOLINE_FLAG_V2_DIRECTION) {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1014                     if 
(lc->direction == GPIOLINE_DIRECTION_OUTPUT) {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1015                             int val 
= test_bit(i, vals);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1016  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1017                             ret = 
gpiod_direction_output(desc, val);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1018                             if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23  1019                                     
goto out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1020                     } else {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1021                             ret = 
gpiod_direction_input(desc);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1022                             if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23  1023                                     
goto out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1024                             ret = 
edge_detector_setup(&line->edets[i], lc);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1025                             if (ret)
f3b3ae8752adc5 Kent Gibson 2020-06-23  1026                                     
goto out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1027                     }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1028             }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1029  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1030             
atomic_notifier_call_chain(&desc->gdev->notifier,
f3b3ae8752adc5 Kent Gibson 2020-06-23  1031                                     
   GPIOLINE_CHANGED_REQUESTED, desc);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1032  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1033             dev_dbg(&gdev->dev, 
"registered chardev handle for line %d\n",
f3b3ae8752adc5 Kent Gibson 2020-06-23  1034                     offset);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1035     }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1036  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1037     fd = 
get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1038     if (fd < 0) {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1039             ret = fd;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1040             goto out_free_line;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1041     }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1042  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1043     file = 
anon_inode_getfile("gpio-line",
f3b3ae8752adc5 Kent Gibson 2020-06-23  1044                               
&line_fileops,
f3b3ae8752adc5 Kent Gibson 2020-06-23  1045                               line,
f3b3ae8752adc5 Kent Gibson 2020-06-23  1046                               
O_RDONLY | O_CLOEXEC);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1047     if (IS_ERR(file)) {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1048             ret = PTR_ERR(file);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1049             goto out_put_unused_fd;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1050     }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1051  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1052     linereq.fd = fd;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1053     if (copy_to_user(ip, &linereq, 
sizeof(linereq))) {
f3b3ae8752adc5 Kent Gibson 2020-06-23  1054             /*
f3b3ae8752adc5 Kent Gibson 2020-06-23  1055              * fput() will trigger 
the release() callback, so do not go onto
f3b3ae8752adc5 Kent Gibson 2020-06-23  1056              * the regular error 
cleanup path here.
f3b3ae8752adc5 Kent Gibson 2020-06-23  1057              */
f3b3ae8752adc5 Kent Gibson 2020-06-23  1058             fput(file);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1059             put_unused_fd(fd);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1060             return -EFAULT;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1061     }
f3b3ae8752adc5 Kent Gibson 2020-06-23  1062  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1063     fd_install(fd, file);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1064  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1065     dev_dbg(&gdev->dev, "registered 
chardev handle for %d lines\n",
f3b3ae8752adc5 Kent Gibson 2020-06-23  1066             line->num_descs);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1067  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1068     return 0;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1069  
f3b3ae8752adc5 Kent Gibson 2020-06-23  1070  out_put_unused_fd:
f3b3ae8752adc5 Kent Gibson 2020-06-23  1071     put_unused_fd(fd);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1072  out_free_line:
f3b3ae8752adc5 Kent Gibson 2020-06-23  1073     line_free(line);
f3b3ae8752adc5 Kent Gibson 2020-06-23  1074     return ret;
f3b3ae8752adc5 Kent Gibson 2020-06-23  1075  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]

Attachment: .config.gz
Description: application/gzip

Reply via email to