11f5207b7SJohn Levon#!/bin/bash
21f5207b7SJohn Levon
31f5207b7SJohn Levondb_file=$1
41f5207b7SJohn Levoncat << EOF | sqlite3 $db_file
51f5207b7SJohn Levon/* we only care about the main ->read/write() functions. */
61f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->read' and file != 'fs/read_write.c';
71f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->write' and file != 'fs/read_write.c';
81f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->read' and caller != '__vfs_read';
91f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->write' and caller != '__vfs_write';
101f5207b7SJohn Levondelete from function_ptr where function = '(struct file_operations)->read';
111f5207b7SJohn Levondelete from function_ptr where function = '(struct file_operations)->write';
121f5207b7SJohn Levondelete from caller_info where function = '__vfs_write' and caller != 'vfs_write';
131f5207b7SJohn Levondelete from caller_info where function = '__vfs_read' and caller != 'vfs_read';
141f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->write' and caller = 'do_loop_readv_writev';
151f5207b7SJohn Levondelete from caller_info where function = 'do_splice_from' and caller = 'direct_splice_actor';
161f5207b7SJohn Levon
171f5207b7SJohn Levon/* delete these function pointers which cause false positives */
181f5207b7SJohn Levondelete from caller_info where function = '(struct file_operations)->open' and type != 0;
191f5207b7SJohn Levondelete from caller_info where function = '(struct notifier_block)->notifier_call' and type != 0;
201f5207b7SJohn Levondelete from caller_info where function = '(struct mISDNchannel)->send' and type != 0;
211f5207b7SJohn Levondelete from caller_info where function = '(struct irq_router)->get' and type != 0;
221f5207b7SJohn Levondelete from caller_info where function = '(struct irq_router)->set' and type != 0;
231f5207b7SJohn Levondelete from caller_info where function = '(struct net_device_ops)->ndo_change_mtu' and caller = 'i40e_dbg_netdev_ops_write';
241f5207b7SJohn Levondelete from caller_info where function = '(struct timer_list)->function' and type != 0;
251f5207b7SJohn Levon
26efe51d0cSJohn Levon/* 8017 is USER_DATA and  9017 is USER_DATA_SET */
27efe51d0cSJohn Levondelete from caller_info where function = 'dev_hard_start_xmit' and type = 8017;
281f5207b7SJohn Levondelete from return_states where function='vscnprintf' and type = 9017;
291f5207b7SJohn Levondelete from return_states where function='scnprintf' and type = 9017;
301f5207b7SJohn Levondelete from return_states where function='vsnprintf' and type = 9017;
311f5207b7SJohn Levondelete from return_states where function='snprintf' and type = 9017;
321f5207b7SJohn Levondelete from return_states where function='sprintf' and type = 9017;
331f5207b7SJohn Levondelete from return_states where function='vscnprintf' and type = 8017;
341f5207b7SJohn Levondelete from return_states where function='scnprintf' and type = 8017;
351f5207b7SJohn Levondelete from return_states where function='vsnprintf' and type = 8017;
361f5207b7SJohn Levondelete from return_states where function='snprintf' and type = 8017;
371f5207b7SJohn Levondelete from return_states where function='sprintf' and type = 8017;
381f5207b7SJohn Levon/* There is something setting skb->sk->sk_mark and friends to user_data and */
391f5207b7SJohn Levon/* because of recursion it gets passed to everything and is impossible to debug */
401f5207b7SJohn Levondelete from caller_info where function = '__dev_queue_xmit' and type = 8017;
411f5207b7SJohn Levondelete from caller_info where function = '__netdev_start_xmit' and type = 8017;
42efe51d0cSJohn Levondelete from caller_info where function = '(struct packet_type)->func' and type = 8017;
43efe51d0cSJohn Levondelete from caller_info where function = '(struct bio)->bi_end_io' and type = 8017;
44c85f09ccSJohn Levondelete from caller_info where type = 8017 and key = '*\$->bi_private';
45c85f09ccSJohn Levondelete from caller_info where type = 8017 and key = '\$->bi_private';
46efe51d0cSJohn Levondelete from caller_info where caller = 'NF_HOOK_COND' and type = 8017;
47efe51d0cSJohn Levondelete from caller_info where caller = 'NF_HOOK' and type = 8017;
481f5207b7SJohn Levon/* comparison doesn't deal with chunks, I guess.  */
491f5207b7SJohn Levondelete from return_states where function='get_tty_driver' and type = 8017;
501f5207b7SJohn Levondelete from caller_info where caller = 'snd_ctl_elem_write' and function = '(struct snd_kcontrol)->put' and type = 8017;
511f5207b7SJohn Levondelete from caller_info where caller = 'snd_ctl_elem_read' and function = '(struct snd_kcontrol)->get' and type = 8017;
521f5207b7SJohn Levondelete from caller_info where function = 'nf_tables_newexpr' and type = 8017 and key = '\$->family';
531f5207b7SJohn Levondelete from caller_info where caller = 'fb_set_var' and function = '(struct fb_ops)->fb_set_par' and type = 8017 and parameter = 0;
541f5207b7SJohn Levondelete from return_states where function = 'tty_lookup_driver' and parameter = 2 and type = 8017;
55c85f09ccSJohn Levondelete from caller_info where function = 'iomap_apply' and type = 8017 and key = '*\$';
561f5207b7SJohn Levon
57efe51d0cSJohn Levoninsert into caller_info values ('userspace', '', 'compat_sys_ioctl', 0, 0, 8017, 0, '\$', '1');
58efe51d0cSJohn Levoninsert into caller_info values ('userspace', '', 'compat_sys_ioctl', 0, 0, 8017, 1, '\$', '1');
59efe51d0cSJohn Levoninsert into caller_info values ('userspace', '', 'compat_sys_ioctl', 0, 0, 8017, 2, '\$', '1');
601f5207b7SJohn Levon
611f5207b7SJohn Levondelete from caller_info where function = '(struct timer_list)->function' and parameter = 0;
621f5207b7SJohn Levon
631f5207b7SJohn Levon/*
641f5207b7SJohn Levon * rw_verify_area is a very central function for the kernel.  The 1000000000
651f5207b7SJohn Levon * isn't accurate but I've picked it so that we can add "pos + count" without
661f5207b7SJohn Levon * wrapping on 32 bits.
671f5207b7SJohn Levon */
681f5207b7SJohn Levondelete from return_states where function = 'rw_verify_area';
691f5207b7SJohn Levoninsert into return_states values ('faked', 'rw_verify_area', 0, 1, '0-1000000000[<=\$3]', 0, 0,   -1,      '', '');
701f5207b7SJohn Levoninsert into return_states values ('faked', 'rw_verify_area', 0, 1, '0-1000000000[<=\$3]', 0, 104,  2, '*\$', '0-1000000000');
711f5207b7SJohn Levoninsert into return_states values ('faked', 'rw_verify_area', 0, 1, '0-1000000000[<=\$3]', 0, 103, 3,  '\$', '0-1000000000');
721f5207b7SJohn Levoninsert into return_states values ('faked', 'rw_verify_area', 0, 2, '(-4095)-(-1)',     0, 0,   -1,      '', '');
731f5207b7SJohn Levon
741f5207b7SJohn Levondelete from return_states where function = 'is_kernel_rodata';
751f5207b7SJohn Levoninsert into return_states values ('faked', 'is_kernel_rodata', 0, 1, '1', 0, 0,   -1,  '', '');
76efe51d0cSJohn Levoninsert into return_states values ('faked', 'is_kernel_rodata', 0, 1, '1', 0, 103,  0,  '\$', '4096-ptr_max');
771f5207b7SJohn Levoninsert into return_states values ('faked', 'is_kernel_rodata', 0, 2, '0', 0, 0,   -1,  '', '');
781f5207b7SJohn Levon
791f5207b7SJohn Levon/*
801f5207b7SJohn Levon * Other kmalloc hacking.
811f5207b7SJohn Levon */
821f5207b7SJohn Levondelete from return_states where function = 'vmalloc';
83efe51d0cSJohn Levoninsert into return_states values ('faked', 'vmalloc', 0, 1, '4096-ptr_max', 0,    0, -1, '', '');
84efe51d0cSJohn Levoninsert into return_states values ('faked', 'vmalloc', 0, 1, '4096-ptr_max', 0, 103,  0, '\$', '1-128000000');
851f5207b7SJohn Levoninsert into return_states values ('faked', 'vmalloc', 0, 2, '0', 0,    0,  -1, '', '');
861f5207b7SJohn Levon
871f5207b7SJohn Levondelete from return_states where function = 'ksize';
881f5207b7SJohn Levoninsert into return_states values ('faked', 'ksize', 0, 1, '0', 0,    0, -1, '', '');
891f5207b7SJohn Levoninsert into return_states values ('faked', 'ksize', 0, 1, '0', 0, 103,  0, '\$', '16');
901f5207b7SJohn Levoninsert into return_states values ('faked', 'ksize', 0, 2, '1-4000000', 0,    0,  -1, '', '');
911f5207b7SJohn Levon
921f5207b7SJohn Levon/* store a bunch of capped functions */
931f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = 'copy_to_user';
941f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = '_copy_to_user';
951f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = '__copy_to_user';
961f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = 'copy_from_user';
971f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = '_copy_from_user';
981f5207b7SJohn Levonupdate return_states set return = '0-u32max[<=\$2]' where function = '__copy_from_user';
991f5207b7SJohn Levon
1001f5207b7SJohn Levonupdate return_states set return = '0-8' where function = '__arch_hweight8';
1011f5207b7SJohn Levonupdate return_states set return = '0-16' where function = '__arch_hweight16';
1021f5207b7SJohn Levonupdate return_states set return = '0-32' where function = '__arch_hweight32';
1031f5207b7SJohn Levonupdate return_states set return = '0-64' where function = '__arch_hweight64';
1041f5207b7SJohn Levon
1051f5207b7SJohn Levon/*
1061f5207b7SJohn Levon * Preserve the value across byte swapping.  By the time we use it for math it
1071f5207b7SJohn Levon * will be byte swapped back to CPU endian.
1081f5207b7SJohn Levon */
1091f5207b7SJohn Levonupdate return_states set return = '0-u64max[==\$0]' where function = '__fswab64';
1101f5207b7SJohn Levonupdate return_states set return = '0-u32max[==\$0]' where function = '__fswab32';
1111f5207b7SJohn Levonupdate return_states set return = '0-u16max[==\$0]' where function = '__fswab16';
1121f5207b7SJohn Levonupdate return_states set return = '0-u64max[==\$0]' where function = '__builtin_bswap64';
1131f5207b7SJohn Levonupdate return_states set return = '0-u32max[==\$0]' where function = '__builtin_bswap32';
1141f5207b7SJohn Levonupdate return_states set return = '0-u16max[==\$0]' where function = '__builtin_bswap16';
1151f5207b7SJohn Levon
1161f5207b7SJohn Levondelete from return_states where function = 'bitmap_allocate_region' and return = '1';
1171f5207b7SJohn Levon/* Just delete a lot of returns that everyone ignores */
1181f5207b7SJohn Levondelete from return_states where file = 'drivers/pci/access.c' and (return >= 129 and return <= 137);
1191f5207b7SJohn Levon
1201f5207b7SJohn Levon/* Smatch can't parse wait_for_completion() */
1211f5207b7SJohn Levonupdate return_states set return = '(-108),(-22),0' where function = '__spi_sync' and return = '(-115),(-108),(-22)';
1221f5207b7SJohn Levon
1231f5207b7SJohn Levondelete from caller_info where caller = '__kernel_write';
1241f5207b7SJohn Levon
1251f5207b7SJohn Levon/* We sometimes use pre-allocated 4097 byte buffers for performance critical code but pretend it is always PAGE_SIZE */
1261f5207b7SJohn Levonupdate caller_info set value = 4096 where caller='kernfs_file_direct_read' and function='(struct kernfs_ops)->read' and type = 1002 and parameter = 1;
1271f5207b7SJohn Levon/* let's pretend firewire doesn't exist */
1281f5207b7SJohn Levondelete from caller_info where caller='init_fw_attribute_group' and function='(struct device_attribute)->show';
1291f5207b7SJohn Levon/* and let's fake the next dev_attr_show() call entirely */
1301f5207b7SJohn Levondelete from caller_info where caller='sysfs_kf_seq_show' and function='(struct sysfs_ops)->show';
131efe51d0cSJohn Levoninsert into caller_info values ('fake', 'sysfs_kf_seq_show', '(struct sysfs_ops)->show', 0, 0, 1001, 0, '\$', '4096-ptr_max');
1321f5207b7SJohn Levoninsert into caller_info values ('fake', 'sysfs_kf_seq_show', '(struct sysfs_ops)->show', 0, 0, 1002, 2, '\$', '4096');
133efe51d0cSJohn Levoninsert into caller_info values ('fake', 'sysfs_kf_seq_show', '(struct sysfs_ops)->show', 0, 0, 1001, 2, '\$', '4096-ptr_max');
1341f5207b7SJohn Levoninsert into caller_info values ('fake', 'sysfs_kf_seq_show', '(struct sysfs_ops)->show', 0, 0, 0,   -1, ''  , '');
1351f5207b7SJohn Levon/* config fs confuses smatch a little */
1361f5207b7SJohn Levonupdate caller_info set value = 4096 where caller='fill_read_buffer' and function='(struct configfs_item_operations)->show_attribute' and type = 1002 and parameter = 2;
1371f5207b7SJohn Levon
1381f5207b7SJohn Levon/* smatch sees the memset() but not the subsequent changes */
1391f5207b7SJohn Levonupdate return_states set value = "" where function = 'gfs2_ea_find' and return = '0' and type = 101 and parameter = 3;
1401f5207b7SJohn Levon
1411f5207b7SJohn Levondelete from type_value where type = '(struct fd)->file';
1421f5207b7SJohn Levondelete from type_value where type = '(struct fd)->flags';
1431f5207b7SJohn Levon
1441f5207b7SJohn Levon/* This is sometimes an enum or a u64 */
1451f5207b7SJohn Levondelete from type_value where type = '(struct mc_cmd_header)->status';
1461f5207b7SJohn Levon
1471f5207b7SJohn Levon/* this is handled in check_kernel.c */
1481f5207b7SJohn Levondelete from return_states where function = "__write_once_size";
1491f5207b7SJohn Levon
1501f5207b7SJohn Levonupdate return_states set value = "s32min-s32max[\$1]" where function = 'atomic_set' and parameter = 0 and type = 1025;
1511f5207b7SJohn Levon
1521f5207b7SJohn Levon/* handled in the check itself */
1531f5207b7SJohn Levondelete from return_states where function = 'atomic_inc_return' and (type = 8023 or type = 8024);
1541f5207b7SJohn Levondelete from return_states where function = 'atomic_add_return' and (type = 8023 or type = 8024);
1551f5207b7SJohn Levondelete from return_states where function = 'atomic_sub_return' and (type = 8023 or type = 8024);
1561f5207b7SJohn Levondelete from return_states where function = 'atomic_sub_and_test' and (type = 8023 or type = 8024);
1571f5207b7SJohn Levondelete from return_states where function = 'atomic_dec_and_test' and (type = 8023 or type = 8024);
1581f5207b7SJohn Levondelete from return_states where function = 'atomic_dec' and (type = 8023 or type = 8024);
1591f5207b7SJohn Levondelete from return_states where function = 'atomic_inc' and (type = 8023 or type = 8024);
1601f5207b7SJohn Levondelete from return_states where function = 'atomic_sub' and (type = 8023 or type = 8024);
1611f5207b7SJohn Levondelete from return_states where function = 'refcount_add_not_zero' and (type = 8023 or type = 8024);
1621f5207b7SJohn Levondelete from return_states where function = 'refcount_inc_not_zero' and (type = 8023 or type = 8024);
1631f5207b7SJohn Levondelete from return_states where function = 'refcount_sub_and_test' and (type = 8023 or type = 8024);
1641f5207b7SJohn Levon
1651f5207b7SJohn Levonupdate return_states set return = '0-32,2147483648-2147483690' where function = '_parse_integer' and return = '0';
1661f5207b7SJohn Levonupdate return_states set value = '0-u64max' where function = '_parse_integer' and type = 1025 and parameter = 2 and key = '*$';
1671f5207b7SJohn Levon
1681f5207b7SJohn Levon/* delete some function pointers which are sometimes byte units */
1691f5207b7SJohn Levondelete from caller_info where function = '(struct i2c_algorithm)->master_xfer' and type = 1027;
1701f5207b7SJohn Levon
1711f5207b7SJohn Levon/* this if from READ_ONCE().  We can't know anything about the data.  */
1721f5207b7SJohn Levondelete from type_info where key = '(union anonymous)->__val';
1731f5207b7SJohn Levon
174efe51d0cSJohn Levon/* This is RIO_BAD_SIZE */
175efe51d0cSJohn Levondelete from return_states where file = 'drivers/rapidio/rio-access.c' and return = '129';
176efe51d0cSJohn Levon
177efe51d0cSJohn Levon/* Smatch sucks at loops */
178efe51d0cSJohn Levondelete from return_states where function = 'ata_dev_next' and type = 103;
179efe51d0cSJohn Levon
180c85f09ccSJohn Levon/* The problem is that parsing big function pointers is hard. */
181c85f09ccSJohn Levondelete from return_states where function = 'vfs_get_tree' and type = 1024;
182c85f09ccSJohn Levon
183*5a0e240fSJohn Levon/* Locking stuff goes here.  */
184*5a0e240fSJohn Levonupdate return_states set parameter = -1, key = '\$' where function = 'ipmi_ssif_lock_cond' and type = 8020 and parameter = 1;
185*5a0e240fSJohn Levonupdate return_states set parameter = 1, key = '\$->tree->tree_lock' where function = 'hfs_find_init' and type = 8020 and parameter = 0;
186*5a0e240fSJohn Levondelete from return_states where function = '__oom_kill_process' and type = 8021;
187*5a0e240fSJohn Levon
1881f5207b7SJohn LevonEOF
1891f5207b7SJohn Levon
1901f5207b7SJohn Levon# fixme: this is totally broken
1911f5207b7SJohn Levoncall_id=$(echo "select distinct call_id from caller_info where function = '__kernel_write';" | sqlite3 $db_file)
1921f5207b7SJohn Levonfor id in $call_id ; do
193efe51d0cSJohn Levon    echo "insert into caller_info values ('fake', '', '__kernel_write', $id, 0, 8017, 1, '*\$', '');" | sqlite3 $db_file
1941f5207b7SJohn Levondone
1951f5207b7SJohn Levon
1961f5207b7SJohn Levonfor i in $(echo "select distinct return from return_states where function = 'clear_user';" | sqlite3 $db_file ) ; do
1971f5207b7SJohn Levon    echo "update return_states set return = \"$i[<=\$1]\" where return = \"$i\" and function = 'clear_user';" | sqlite3 $db_file
1981f5207b7SJohn Levondone
1991f5207b7SJohn Levon
2001f5207b7SJohn Levonecho "select distinct file, function from function_ptr where ptr='(struct rtl_hal_ops)->set_hw_reg';" \
2011f5207b7SJohn Levon        | sqlite3 $db_file | sed -e 's/|/ /' | while read file function ; do
2021f5207b7SJohn Levon
2031f5207b7SJohn Levon    drv=$(echo $file | perl -ne 's/.*\/rtlwifi\/(.*?)\/sw.c/$1/; print')
2041f5207b7SJohn Levon    if [ $drv = "" ] ; then
2051f5207b7SJohn Levon        continue
2061f5207b7SJohn Levon    fi
2071f5207b7SJohn Levon
2081f5207b7SJohn Levon    echo "update caller_info
2091f5207b7SJohn Levon          set function = '$drv (struct rtl_hal_ops)->set_hw_reg'
2101f5207b7SJohn Levon          where function = '(struct rtl_hal_ops)->set_hw_reg' and file like 'drivers/net/wireless/rtlwifi/$drv/%';" \
2111f5207b7SJohn Levon         | sqlite3 $db_file
2121f5207b7SJohn Levon
2131f5207b7SJohn Levon    echo "insert into function_ptr values ('$file', '$function', '$drv (struct rtl_hal_ops)->set_hw_reg', 1);" \
2141f5207b7SJohn Levon         | sqlite3 $db_file
2151f5207b7SJohn Levondone
2161f5207b7SJohn Levon
217efe51d0cSJohn Levon
218efe51d0cSJohn Levonfor func in __kmalloc __kmalloc_track_caller ; do
219efe51d0cSJohn Levon
220efe51d0cSJohn Levon    cat << EOF | sqlite3 $db_file
221efe51d0cSJohn Levondelete from return_states where function = '$func';
222efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 1, '16', 0,    0,  -1, '', '');
223efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 1, '16', 0, 103,   0, '\$', '0');
224efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 2, '4096-ptr_max', 0,    0, -1, '', '');
225efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 2, '4096-ptr_max', 0, 103,  0, '\$', '1-4000000');
226efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 2, '4096-ptr_max', 0, 1037,  -1, '', 400);
227efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 3, '0', 0,    0,  -1, '', '');
228efe51d0cSJohn Levoninsert into return_states values ('faked', '$func', 0, 3, '0', 0,    103,  0, '\$', '1-long_max');
229efe51d0cSJohn LevonEOF
230efe51d0cSJohn Levondone
231