| /* This is a very simplified version of CVE-2017-18549, |
| a use of uninitialized padding values affecting the Linux kernel |
| (and thus GPLv2). |
| |
| It was fixed by e.g. 342ffc26693b528648bdc9377e51e4f2450b4860 on linux-4.13.y |
| in linux-stable. */ |
| |
| #include "analyzer-decls.h" |
| #include <string.h> |
| |
| typedef unsigned int __u32; |
| typedef unsigned int u32; |
| typedef unsigned char u8; |
| |
| /* Adapted from include/uapi/linux/types.h */ |
| |
| #define __bitwise |
| typedef __u32 __bitwise __le32; |
| |
| /* Adapted from drivers/scsi/aacraid/aacraid.h */ |
| |
| #define AAC_SENSE_BUFFERSIZE 30 |
| |
| struct aac_srb_reply |
| { |
| __le32 status; |
| __le32 srb_status; |
| __le32 scsi_status; |
| __le32 data_xfer_length; |
| __le32 sense_data_size; |
| u8 sense_data[AAC_SENSE_BUFFERSIZE]; |
| |
| /* Manually added to help verify the fix. */ |
| u8 padding[2]; |
| }; |
| |
| #define ST_OK 0 |
| #define SRB_STATUS_SUCCESS 0x01 |
| |
| extern void check_uninit (u8 v); |
| |
| /* Adapted from drivers/scsi/aacraid/commctrl.c */ |
| |
| static int aac_send_raw_srb(/* [...snip...] */) |
| { |
| u32 byte_count = 0; |
| |
| /* [...snip...] */ |
| |
| struct aac_srb_reply reply; |
| |
| reply.status = ST_OK; |
| |
| /* [...snip...] */ |
| |
| reply.srb_status = SRB_STATUS_SUCCESS; |
| reply.scsi_status = 0; |
| reply.data_xfer_length = byte_count; |
| reply.sense_data_size = 0; |
| memset(reply.sense_data, 0, AAC_SENSE_BUFFERSIZE); |
| |
| /* [...snip...] */ |
| |
| __analyzer_eval (reply.status == ST_OK); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.srb_status == SRB_STATUS_SUCCESS); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.scsi_status == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.data_xfer_length == byte_count); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data_size == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data[0] == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data[AAC_SENSE_BUFFERSIZE - 1] == 0); /* { dg-warning "TRUE" } */ |
| check_uninit (reply.padding[0]); /* { dg-warning "uninitialized value" } */ |
| check_uninit (reply.padding[1]); /* { dg-warning "uninitialized value" } */ |
| } |
| |
| static int aac_send_raw_srb_fixed(/* [...snip...] */) |
| { |
| u32 byte_count = 0; |
| |
| /* [...snip...] */ |
| |
| struct aac_srb_reply reply; |
| |
| /* This is the fix. */ |
| memset(&reply, 0, sizeof(reply)); |
| |
| reply.status = ST_OK; |
| |
| /* [...snip...] */ |
| |
| reply.srb_status = SRB_STATUS_SUCCESS; |
| reply.scsi_status = 0; |
| reply.data_xfer_length = byte_count; |
| reply.sense_data_size = 0; |
| memset(reply.sense_data, 0, AAC_SENSE_BUFFERSIZE); |
| |
| /* [...snip...] */ |
| |
| __analyzer_eval (reply.status == ST_OK); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.srb_status == SRB_STATUS_SUCCESS); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.scsi_status == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.data_xfer_length == byte_count); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data_size == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data[0] == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.sense_data[AAC_SENSE_BUFFERSIZE - 1] == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.padding[0] == 0); /* { dg-warning "TRUE" } */ |
| __analyzer_eval (reply.padding[1] == 0); /* { dg-warning "TRUE" } */ |
| } |