lPengfei Ding & Chenfu BaolSecurity Researcher & Developer@ Baidu X-Lab
lFocused on Mobile, IoT andLinux kernel security

l Introductionl Past Compat Vulnerabilitiesl Newly Identified Compat Vulnerabilitiesl Advices & Mitigationsl Conclusions

l 32-bit compatibility mode in 64-bit Linux kernels

32-bit processuserprocesscompatsyscallsystemcall
64-bit process

64-bitsyscalll Mainly used to handle the differences in the data
sizes
l Many system calls have parameters with different
sizes in 32-bit and 64-bit systeml long, pointer, …

l Convert the values of these parameters tocorresponding 64-bit values

l Code redundancy requires more maintenanceefforts, thus introducing more security risksl Additional definition of data structures, typeconversion and data processing logic expose new
attack surfaces

l Occasionally discoveredl Mostly in device drivers
l Mostly caused by inconsistency between
compat and non-compat model Inconsistency of data structure definitionl Inconsistency of user input validation logic

l Inconsistency of data structure definition

memcpy leads to stack overflow!

l Inconsistency ofuser input
validation logic
eeprom_init_config
validates user input,
while its compat version
eeprom_init_config32
does not validate userinput
patch url : https://source.codea urora. org/quic/la/kernel /ms m-3 .18/ commit/ drivers/ media /platfor m/ ms m/ camera_v2/ sensor/ eepr om? h=rel/ ms m-3. 18.r5 &i d=53 93 99acbae cba 7af7c4 11 f6 f28a c0 189e 45 9bb5

l Inconsistency ofuser input
validation logic
is_compat_task can
reduce code
redundancy, but
inconsistency still
existspatch url :https://source.codeaurora.org/quic/la/kernel/msm-3.18/commit/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c?h=rel/msm-3.18.r5&id=17c31f3f3438c9f3e05b0d92c70b2b65d430d6cd

l Past research on compat vulnerabilities only
focuses on normal program logic
l In device drivers, compat and non-compat codes
are often mixed togetherl Can mixed codes cause abnormal program logic?

ioctlsyscall entry

file_operations

unlocked_ioctl（fd,cmd64,pstruct64）

64-bit processcompat_ioctl（fd,cmd32,pstruct32）

32-bit processcmd32

common
cmd

cmd64

cmd64

check user input

check user input&convert to
cmd64 pstruct64
cmd32

ioctl

goto kernel

file_operations

unlocked_ioctl（fd,cmd64,pstruct64）

64-bit processcommon cmd

return touser

commonfunction

64-bit process

32-bit processcommon cmd

compat_ioctl（fd,cmd32,pstruct32）

32-bit process

convert to
pstruct32

l compat_ioctl will make conversion according to the value of cmd32
l What if we intentionally confuse compat_ioctl

parameters with unlocked_ioctl parameters?
1.compat_ioctl(fd, cmd64, pstruct32)
2.compat_ioctl(fd, cmd64, pstruct64)
3.compat_ioctl(fd, cmd32, pstruct64)
4.unlocked_ioctl(fd, cmd32, pstruct64)
5.unlocked_ioctl(fd, cmd32, pstruct32)
6.unlocked_ioctl(fd, cmd64, pstruct32)

1.compat_ioctl(fd, cmd64, pstruct32)
2.compat_ioctl(fd, cmd64, pstruct64)
3.compat_ioctl(fd, cmd32, pstruct64)
4.unlocked_ioctl(fd, cmd32, pstruct64)
5.unlocked_ioctl(fd, cmd32, pstruct32)
6.unlocked_ioctl(fd, cmd64, pstruct32)

l unlocked_ioctl does not have conversion
behavior, cmd32 parameters will befiltered, thus will not cause security
problems.
l 4 and 5 are ruled out

l Processing logic of pstruct parameter in
ioctl depends on the value of cmd, so we
ignore pstruct(pstruct32，pstruct64)
parameter, only focusing on how changesof cmd parameter will affect ioctl

cmd32

common
cmd

cmd64

cmd64

check user input

check user input &convert to
cmd64 pstruct64
cmd32

ioctl

file_operations

unlocked_ioctl（fd,cmd64,pstruct64）

64-bit processcommon cmd

return touser

commonfunction
cmd64

goto kernel

64-bit process

32-bit processcommon cmd

compat_ioctl
compat_ioctl（fd,cmd32,pstruct32）（fd,cmd64,pstruct）

32-bit process

convert topstruct32

l Existing Linux syscall fuzzing tools do not support
compatl Trinityl Syzkallerl We extended Trinity and syzkaller and discovered
more vulnerabilities

l Bypassing verification on user input array
length can lead to out-of-bounds R/W to thisarray, thus causing privilege escalationl Bypassing verification on user input pointervalue can lead to arbitrary memory read, thus
causing information leakage

l Operate kernel memory instead of user memory incheck & conversion, which increases the security risk
when check & conversion is bypassedl Kmalloc vs compat_alloc_user_spacel When is_compat_task is used in common function, it
is easy to cause logic confusion, and it is more likely
to cause security problems when check & conversion
is bypassedstatic long msm_cpp_subdev_fops_compat_ioctl(struct file *file,unsigned int cmd, unsigned long arg)

case VIDIOC_MSM_CPP_POP_STREAM_BUFFER32:{...
if (copy_from_user(&k32_frame_info,(void __user *)kp_ioctl.ioctl_ptr,
sizeof(k32_frame_info))) {...
cmd = VIDIOC_MSM_CPP_POP_STREAM_BUFFER;
break;

static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr)...
/* For compat task, source ptr is in kernel space */if (is_compat_task()) {memcpy(dst_ptr, ioctl_ptr->ioctl_ptr, ioctl_ptr->len);

The processing flow ofqualcomm driver function
msm_cpp_subdev_fops_compat_ioctl
to cmd32:
VIDIOC_MSM_CPP_POP_STREAM_BUFFER32

is shown in the left diagram.
If we pass directly to its corresponding
cmd64:
VIDIOC_MSM_CPP_POP_STREAM_BUFFER ,the validation of user space pointerioctl_ptr will be bypassed, so it can be
assigned to any value by the user,
resulting in arbitrary address accesswhen using memcpy.

#ifdef CONFIG_COMPAT
static long msm_flash_subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)

switch (cmd) {case VIDIOC_MSM_FLASH_CFG32:
cmd = VIDIOC_MSM_FLASH_CFG;...
flash_data.cfg.flash_init_info = &flash_init_info;
if (copy_from_user(&flash_init_info32,(void *)compat_ptr(u32->cfg.flash_init_info),
sizeof(struct msm_flash_init_info_t32))) {static int32_t msm_flash_init(struct msm_flash_ctrl_t *flash_ctrl,struct msm_flash_cfg_data_t *flash_data){...
if (flash_data->cfg.flash_init_info->flash_driver_type ==FLASH_DRIVER_DEFAULT) {The processing flow ofqualcomm driver function
msm_flash_subdev_do_ioctl
to cmd32:
VIDIOC_MSM_FLASH_CFG32
is shown in the left diagram.
copy_from_user checks user spacepointer cfg.flash_init_info .
If we pass directly to its corresponding
cmd64:VIDIOC_MSM_FLASH_CFG,
the validation will be bypassed, socfg.flash_init_info can be assigned toany value , resulting in arbitrary
address access when it’s dereferenced.

l Try to use compat_alloc_user_space instead of kmalloc during entire
user input check & conversionl Try to avoid using is_compat_task in common functionl Try to use structs instead of pointers in user input to minimize
validation of user input

l Development and test engineers should strengthen thetesting and auditing of compat codes
l Fuzz tools and code auditing tools should give more
attention to compat codesl Security researchers can continue to explore
compat attack on more platforms

l Concept and security risks of compat, as well as somecompat vulnerabilities in the pastl New type of compat vulnerabilities in Linux device drivers
l How to discover this kind of vulnerabilities and how toavoid them in development

Thanks!