Hi DM Maintainers and kernel hardenning people, drivers/md/dm-ioctl.c 1931 static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel, 1932 int ioctl_flags, struct dm_ioctl **param, int *param_flags) 1933 { 1934 struct dm_ioctl *dmi; 1935 int secure_data; 1936 const size_t minimum_data_size = offsetof(struct dm_ioctl, data); 1937 1938 /* check_version() already copied version from userspace, avoid TOCTOU */ 1939 if (copy_from_user((char *)param_kernel + sizeof(param_kernel->version), 1940 (char __user *)user + sizeof(param_kernel->version), 1941 minimum_data_size - sizeof(param_kernel->version))) 1942 return -EFAULT; 1943 1944 if (unlikely(param_kernel->data_size < minimum_data_size) || 1945 unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) { So what's happening here is that struct dm_ioctl->data[] is declared as a 7 byte array, but it's actually a variable size array which could be more or less than 7 bytes. 1946 DMERR("Invalid data size in the ioctl structure: %u", 1947 param_kernel->data_size); 1948 return -EINVAL; 1949 } 1950 1951 secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG; 1952 1953 *param_flags = secure_data ? DM_WIPE_BUFFER : 0; 1954 1955 if (ioctl_flags & IOCTL_FLAGS_NO_PARAMS) { 1956 dmi = param_kernel; 1957 dmi->data_size = minimum_data_size; 1958 goto data_copied; 1959 } 1960 1961 /* 1962 * Use __GFP_HIGH to avoid low memory issues when a device is 1963 * suspended and the ioctl is needed to resume it. 1964 * Use kmalloc() rather than vmalloc() when we can. 1965 */ 1966 dmi = NULL; 1967 dmi = kvmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH); We allocate the correct size of the variable element array. 1968 1969 if (!dmi) { 1970 if (secure_data && clear_user(user, param_kernel->data_size)) 1971 return -EFAULT; 1972 return -ENOMEM; 1973 } 1974 1975 *param_flags |= DM_PARAMS_MALLOC; 1976 1977 /* Copy from param_kernel (which was already copied from user) */ 1978 memcpy(dmi, param_kernel, minimum_data_size); 1979 --> 1980 if (copy_from_user(&dmi->data, (char __user *)user + minimum_data_size, 1981 param_kernel->data_size - minimum_data_size)) Doesn't the kernel hardenning stuff have run time checks for if we write beyond the end of a 7 byte array? Why not just declare it as a zero element array? 1982 goto bad; 1983 data_copied: 1984 /* Wipe the user buffer so we do not return it to userspace */ 1985 if (secure_data && clear_user(user, param_kernel->data_size)) 1986 goto bad; 1987 1988 *param = dmi; 1989 return 0; 1990 1991 bad: 1992 free_params(dmi, param_kernel->data_size, *param_flags); 1993 1994 return -EFAULT; 1995 } regards, dan carpenter