[ 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 <lkp@xxxxxxxxx> Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> 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/kbuild-all@xxxxxxxxxxxx
Attachment:
.config.gz
Description: application/gzip