Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

treewide: Change list_sort to use const pointers

list_sort() internally casts the comparison function passed to it
to a different type with constant struct list_head pointers, and
uses this pointer to call the functions, which trips indirect call
Control-Flow Integrity (CFI) checking.

Instead of removing the consts, this change defines the
list_cmp_func_t type and changes the comparison function types of
all list_sort() callers to use const pointers, thus avoiding type
mismatches.

Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20210408182843.1754385-10-samitolvanen@google.com

authored by

Sami Tolvanen and committed by
Kees Cook
4f0f586b 9f5b4009

+90 -72
+4 -4
arch/arm64/kvm/vgic/vgic-its.c
··· 2190 2190 return offset; 2191 2191 } 2192 2192 2193 - static int vgic_its_ite_cmp(void *priv, struct list_head *a, 2194 - struct list_head *b) 2193 + static int vgic_its_ite_cmp(void *priv, const struct list_head *a, 2194 + const struct list_head *b) 2195 2195 { 2196 2196 struct its_ite *itea = container_of(a, struct its_ite, ite_list); 2197 2197 struct its_ite *iteb = container_of(b, struct its_ite, ite_list); ··· 2329 2329 return offset; 2330 2330 } 2331 2331 2332 - static int vgic_its_device_cmp(void *priv, struct list_head *a, 2333 - struct list_head *b) 2332 + static int vgic_its_device_cmp(void *priv, const struct list_head *a, 2333 + const struct list_head *b) 2334 2334 { 2335 2335 struct its_device *deva = container_of(a, struct its_device, dev_list); 2336 2336 struct its_device *devb = container_of(b, struct its_device, dev_list);
+2 -1
arch/arm64/kvm/vgic/vgic.c
··· 255 255 * Return negative if "a" sorts before "b", 0 to preserve order, and positive 256 256 * to sort "b" before "a". 257 257 */ 258 - static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b) 258 + static int vgic_irq_cmp(void *priv, const struct list_head *a, 259 + const struct list_head *b) 259 260 { 260 261 struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list); 261 262 struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+2 -1
block/blk-mq-sched.c
··· 75 75 blk_mq_run_hw_queue(hctx, true); 76 76 } 77 77 78 - static int sched_rq_cmp(void *priv, struct list_head *a, struct list_head *b) 78 + static int sched_rq_cmp(void *priv, const struct list_head *a, 79 + const struct list_head *b) 79 80 { 80 81 struct request *rqa = container_of(a, struct request, queuelist); 81 82 struct request *rqb = container_of(b, struct request, queuelist);
+2 -1
block/blk-mq.c
··· 1895 1895 spin_unlock(&ctx->lock); 1896 1896 } 1897 1897 1898 - static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) 1898 + static int plug_rq_cmp(void *priv, const struct list_head *a, 1899 + const struct list_head *b) 1899 1900 { 1900 1901 struct request *rqa = container_of(a, struct request, queuelist); 1901 1902 struct request *rqb = container_of(b, struct request, queuelist);
+2 -1
drivers/acpi/nfit/core.c
··· 1195 1195 return 0; 1196 1196 } 1197 1197 1198 - static int nfit_mem_cmp(void *priv, struct list_head *_a, struct list_head *_b) 1198 + static int nfit_mem_cmp(void *priv, const struct list_head *_a, 1199 + const struct list_head *_b) 1199 1200 { 1200 1201 struct nfit_mem *a = container_of(_a, typeof(*a), list); 1201 1202 struct nfit_mem *b = container_of(_b, typeof(*b), list);
+2 -1
drivers/acpi/numa/hmat.c
··· 558 558 return updated; 559 559 } 560 560 561 - static int initiator_cmp(void *priv, struct list_head *a, struct list_head *b) 561 + static int initiator_cmp(void *priv, const struct list_head *a, 562 + const struct list_head *b) 562 563 { 563 564 struct memory_initiator *ia; 564 565 struct memory_initiator *ib;
+2 -2
drivers/clk/keystone/sci-clk.c
··· 503 503 504 504 #else 505 505 506 - static int _cmp_sci_clk_list(void *priv, struct list_head *a, 507 - struct list_head *b) 506 + static int _cmp_sci_clk_list(void *priv, const struct list_head *a, 507 + const struct list_head *b) 508 508 { 509 509 struct sci_clk *ca = container_of(a, struct sci_clk, node); 510 510 struct sci_clk *cb = container_of(b, struct sci_clk, node);
+2 -1
drivers/gpu/drm/drm_modes.c
··· 1290 1290 * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or 1291 1291 * positive if @lh_b is better than @lh_a. 1292 1292 */ 1293 - static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b) 1293 + static int drm_mode_compare(void *priv, const struct list_head *lh_a, 1294 + const struct list_head *lh_b) 1294 1295 { 1295 1296 struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head); 1296 1297 struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
+2 -1
drivers/gpu/drm/i915/gt/intel_engine_user.c
··· 49 49 [VIDEO_ENHANCEMENT_CLASS] = I915_ENGINE_CLASS_VIDEO_ENHANCE, 50 50 }; 51 51 52 - static int engine_cmp(void *priv, struct list_head *A, struct list_head *B) 52 + static int engine_cmp(void *priv, const struct list_head *A, 53 + const struct list_head *B) 53 54 { 54 55 const struct intel_engine_cs *a = 55 56 container_of((struct rb_node *)A, typeof(*a), uabi_node);
+1 -1
drivers/gpu/drm/i915/gvt/debugfs.c
··· 41 41 42 42 /* Compare two diff_mmio items. */ 43 43 static int mmio_offset_compare(void *priv, 44 - struct list_head *a, struct list_head *b) 44 + const struct list_head *a, const struct list_head *b) 45 45 { 46 46 struct diff_mmio *ma; 47 47 struct diff_mmio *mb;
+2 -1
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
··· 1076 1076 return exercise_ppgtt(arg, shrink_boom); 1077 1077 } 1078 1078 1079 - static int sort_holes(void *priv, struct list_head *A, struct list_head *B) 1079 + static int sort_holes(void *priv, const struct list_head *A, 1080 + const struct list_head *B) 1080 1081 { 1081 1082 struct drm_mm_node *a = list_entry(A, typeof(*a), hole_stack); 1082 1083 struct drm_mm_node *b = list_entry(B, typeof(*b), hole_stack);
+2 -2
drivers/gpu/drm/radeon/radeon_cs.c
··· 393 393 return 0; 394 394 } 395 395 396 - static int cmp_size_smaller_first(void *priv, struct list_head *a, 397 - struct list_head *b) 396 + static int cmp_size_smaller_first(void *priv, const struct list_head *a, 397 + const struct list_head *b) 398 398 { 399 399 struct radeon_bo_list *la = list_entry(a, struct radeon_bo_list, tv.head); 400 400 struct radeon_bo_list *lb = list_entry(b, struct radeon_bo_list, tv.head);
+2 -1
drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
··· 83 83 return interval; 84 84 } 85 85 86 - static int interval_cmp(void *priv, struct list_head *a, struct list_head *b) 86 + static int interval_cmp(void *priv, const struct list_head *a, 87 + const struct list_head *b) 87 88 { 88 89 struct usnic_uiom_interval_node *node_a, *node_b; 89 90
+1 -1
drivers/interconnect/qcom/bcm-voter.c
··· 39 39 u32 tcs_wait; 40 40 }; 41 41 42 - static int cmp_vcd(void *priv, struct list_head *a, struct list_head *b) 42 + static int cmp_vcd(void *priv, const struct list_head *a, const struct list_head *b) 43 43 { 44 44 const struct qcom_icc_bcm *bcm_a = list_entry(a, struct qcom_icc_bcm, list); 45 45 const struct qcom_icc_bcm *bcm_b = list_entry(b, struct qcom_icc_bcm, list);
+2 -1
drivers/md/raid5.c
··· 953 953 submit_bio_noacct(bio); 954 954 } 955 955 956 - static int cmp_stripe(void *priv, struct list_head *a, struct list_head *b) 956 + static int cmp_stripe(void *priv, const struct list_head *a, 957 + const struct list_head *b) 957 958 { 958 959 const struct r5pending_data *da = list_entry(a, 959 960 struct r5pending_data, sibling);
+2 -2
drivers/misc/sram.c
··· 144 144 } 145 145 } 146 146 147 - static int sram_reserve_cmp(void *priv, struct list_head *a, 148 - struct list_head *b) 147 + static int sram_reserve_cmp(void *priv, const struct list_head *a, 148 + const struct list_head *b) 149 149 { 150 150 struct sram_reserve *ra = list_entry(a, struct sram_reserve, list); 151 151 struct sram_reserve *rb = list_entry(b, struct sram_reserve, list);
+2 -1
drivers/nvme/host/core.c
··· 3855 3855 return ret; 3856 3856 } 3857 3857 3858 - static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) 3858 + static int ns_cmp(void *priv, const struct list_head *a, 3859 + const struct list_head *b) 3859 3860 { 3860 3861 struct nvme_ns *nsa = container_of(a, struct nvme_ns, list); 3861 3862 struct nvme_ns *nsb = container_of(b, struct nvme_ns, list);
+2 -1
drivers/pci/controller/cadence/pcie-cadence-host.c
··· 345 345 return 0; 346 346 } 347 347 348 - static int cdns_pcie_host_dma_ranges_cmp(void *priv, struct list_head *a, struct list_head *b) 348 + static int cdns_pcie_host_dma_ranges_cmp(void *priv, const struct list_head *a, 349 + const struct list_head *b) 349 350 { 350 351 struct resource_entry *entry1, *entry2; 351 352
+2 -1
drivers/spi/spi-loopback-test.c
··· 454 454 u8 *end; 455 455 }; 456 456 457 - static int rx_ranges_cmp(void *priv, struct list_head *a, struct list_head *b) 457 + static int rx_ranges_cmp(void *priv, const struct list_head *a, 458 + const struct list_head *b) 458 459 { 459 460 struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list); 460 461 struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list);
+2 -1
fs/btrfs/raid56.c
··· 1634 1634 /* 1635 1635 * rbios on the plug list are sorted for easier merging. 1636 1636 */ 1637 - static int plug_cmp(void *priv, struct list_head *a, struct list_head *b) 1637 + static int plug_cmp(void *priv, const struct list_head *a, 1638 + const struct list_head *b) 1638 1639 { 1639 1640 struct btrfs_raid_bio *ra = container_of(a, struct btrfs_raid_bio, 1640 1641 plug_list);
+2 -1
fs/btrfs/tree-log.c
··· 4136 4136 return ret; 4137 4137 } 4138 4138 4139 - static int extent_cmp(void *priv, struct list_head *a, struct list_head *b) 4139 + static int extent_cmp(void *priv, const struct list_head *a, 4140 + const struct list_head *b) 4140 4141 { 4141 4142 struct extent_map *em1, *em2; 4142 4143
+2 -1
fs/btrfs/volumes.c
··· 1224 1224 return 0; 1225 1225 } 1226 1226 1227 - static int devid_cmp(void *priv, struct list_head *a, struct list_head *b) 1227 + static int devid_cmp(void *priv, const struct list_head *a, 1228 + const struct list_head *b) 1228 1229 { 1229 1230 struct btrfs_device *dev1, *dev2; 1230 1231
+2 -2
fs/ext4/fsmap.c
··· 354 354 355 355 /* Compare two fsmap items. */ 356 356 static int ext4_getfsmap_compare(void *priv, 357 - struct list_head *a, 358 - struct list_head *b) 357 + const struct list_head *a, 358 + const struct list_head *b) 359 359 { 360 360 struct ext4_fsmap *fa; 361 361 struct ext4_fsmap *fb;
+2 -1
fs/gfs2/glock.c
··· 1732 1732 spin_unlock(&gl->gl_lockref.lock); 1733 1733 } 1734 1734 1735 - static int glock_cmp(void *priv, struct list_head *a, struct list_head *b) 1735 + static int glock_cmp(void *priv, const struct list_head *a, 1736 + const struct list_head *b) 1736 1737 { 1737 1738 struct gfs2_glock *gla, *glb; 1738 1739
+1 -1
fs/gfs2/log.c
··· 695 695 } 696 696 } 697 697 698 - static int ip_cmp(void *priv, struct list_head *a, struct list_head *b) 698 + static int ip_cmp(void *priv, const struct list_head *a, const struct list_head *b) 699 699 { 700 700 struct gfs2_inode *ipa, *ipb; 701 701
+2 -1
fs/gfs2/lops.c
··· 634 634 kunmap_atomic(kaddr); 635 635 } 636 636 637 - static int blocknr_cmp(void *priv, struct list_head *a, struct list_head *b) 637 + static int blocknr_cmp(void *priv, const struct list_head *a, 638 + const struct list_head *b) 638 639 { 639 640 struct gfs2_bufdata *bda, *bdb; 640 641
+2 -1
fs/iomap/buffered-io.c
··· 1155 1155 EXPORT_SYMBOL_GPL(iomap_ioend_try_merge); 1156 1156 1157 1157 static int 1158 - iomap_ioend_compare(void *priv, struct list_head *a, struct list_head *b) 1158 + iomap_ioend_compare(void *priv, const struct list_head *a, 1159 + const struct list_head *b) 1159 1160 { 1160 1161 struct iomap_ioend *ia = container_of(a, struct iomap_ioend, io_list); 1161 1162 struct iomap_ioend *ib = container_of(b, struct iomap_ioend, io_list);
+4 -3
fs/ubifs/gc.c
··· 102 102 * This function compares data nodes @a and @b. Returns %1 if @a has greater 103 103 * inode or block number, and %-1 otherwise. 104 104 */ 105 - static int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) 105 + static int data_nodes_cmp(void *priv, const struct list_head *a, 106 + const struct list_head *b) 106 107 { 107 108 ino_t inuma, inumb; 108 109 struct ubifs_info *c = priv; ··· 146 145 * first and sorted by length in descending order. Directory entry nodes go 147 146 * after inode nodes and are sorted in ascending hash valuer order. 148 147 */ 149 - static int nondata_nodes_cmp(void *priv, struct list_head *a, 150 - struct list_head *b) 148 + static int nondata_nodes_cmp(void *priv, const struct list_head *a, 149 + const struct list_head *b) 151 150 { 152 151 ino_t inuma, inumb; 153 152 struct ubifs_info *c = priv;
+2 -2
fs/ubifs/replay.c
··· 298 298 * entries @a and @b by comparing their sequence numer. Returns %1 if @a has 299 299 * greater sequence number and %-1 otherwise. 300 300 */ 301 - static int replay_entries_cmp(void *priv, struct list_head *a, 302 - struct list_head *b) 301 + static int replay_entries_cmp(void *priv, const struct list_head *a, 302 + const struct list_head *b) 303 303 { 304 304 struct ubifs_info *c = priv; 305 305 struct replay_entry *ra, *rb;
+2 -2
fs/xfs/scrub/bitmap.c
··· 63 63 static int 64 64 xbitmap_range_cmp( 65 65 void *priv, 66 - struct list_head *a, 67 - struct list_head *b) 66 + const struct list_head *a, 67 + const struct list_head *b) 68 68 { 69 69 struct xbitmap_range *ap; 70 70 struct xbitmap_range *bp;
+2 -2
fs/xfs/xfs_bmap_item.c
··· 265 265 static int 266 266 xfs_bmap_update_diff_items( 267 267 void *priv, 268 - struct list_head *a, 269 - struct list_head *b) 268 + const struct list_head *a, 269 + const struct list_head *b) 270 270 { 271 271 struct xfs_bmap_intent *ba; 272 272 struct xfs_bmap_intent *bb;
+3 -3
fs/xfs/xfs_buf.c
··· 2124 2124 */ 2125 2125 static int 2126 2126 xfs_buf_cmp( 2127 - void *priv, 2128 - struct list_head *a, 2129 - struct list_head *b) 2127 + void *priv, 2128 + const struct list_head *a, 2129 + const struct list_head *b) 2130 2130 { 2131 2131 struct xfs_buf *ap = container_of(a, struct xfs_buf, b_list); 2132 2132 struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list);
+2 -2
fs/xfs/xfs_extent_busy.c
··· 629 629 int 630 630 xfs_extent_busy_ag_cmp( 631 631 void *priv, 632 - struct list_head *l1, 633 - struct list_head *l2) 632 + const struct list_head *l1, 633 + const struct list_head *l2) 634 634 { 635 635 struct xfs_extent_busy *b1 = 636 636 container_of(l1, struct xfs_extent_busy, list);
+2 -1
fs/xfs/xfs_extent_busy.h
··· 58 58 xfs_extent_busy_wait_all(struct xfs_mount *mp); 59 59 60 60 int 61 - xfs_extent_busy_ag_cmp(void *priv, struct list_head *a, struct list_head *b); 61 + xfs_extent_busy_ag_cmp(void *priv, const struct list_head *a, 62 + const struct list_head *b); 62 63 63 64 static inline void xfs_extent_busy_sort(struct list_head *list) 64 65 {
+2 -2
fs/xfs/xfs_extfree_item.c
··· 397 397 static int 398 398 xfs_extent_free_diff_items( 399 399 void *priv, 400 - struct list_head *a, 401 - struct list_head *b) 400 + const struct list_head *a, 401 + const struct list_head *b) 402 402 { 403 403 struct xfs_mount *mp = priv; 404 404 struct xfs_extent_free_item *ra;
+2 -2
fs/xfs/xfs_refcount_item.c
··· 269 269 static int 270 270 xfs_refcount_update_diff_items( 271 271 void *priv, 272 - struct list_head *a, 273 - struct list_head *b) 272 + const struct list_head *a, 273 + const struct list_head *b) 274 274 { 275 275 struct xfs_mount *mp = priv; 276 276 struct xfs_refcount_intent *ra;
+2 -2
fs/xfs/xfs_rmap_item.c
··· 337 337 static int 338 338 xfs_rmap_update_diff_items( 339 339 void *priv, 340 - struct list_head *a, 341 - struct list_head *b) 340 + const struct list_head *a, 341 + const struct list_head *b) 342 342 { 343 343 struct xfs_mount *mp = priv; 344 344 struct xfs_rmap_intent *ra;
+4 -3
include/linux/list_sort.h
··· 6 6 7 7 struct list_head; 8 8 9 + typedef int __attribute__((nonnull(2,3))) (*list_cmp_func_t)(void *, 10 + const struct list_head *, const struct list_head *); 11 + 9 12 __attribute__((nonnull(2,3))) 10 - void list_sort(void *priv, struct list_head *head, 11 - int (*cmp)(void *priv, struct list_head *a, 12 - struct list_head *b)); 13 + void list_sort(void *priv, struct list_head *head, list_cmp_func_t cmp); 13 14 #endif
+6 -11
lib/list_sort.c
··· 7 7 #include <linux/list_sort.h> 8 8 #include <linux/list.h> 9 9 10 - typedef int __attribute__((nonnull(2,3))) (*cmp_func)(void *, 11 - struct list_head const *, struct list_head const *); 12 - 13 10 /* 14 11 * Returns a list organized in an intermediate format suited 15 12 * to chaining of merge() calls: null-terminated, no reserved or 16 13 * sentinel head node, "prev" links not maintained. 17 14 */ 18 15 __attribute__((nonnull(2,3,4))) 19 - static struct list_head *merge(void *priv, cmp_func cmp, 16 + static struct list_head *merge(void *priv, list_cmp_func_t cmp, 20 17 struct list_head *a, struct list_head *b) 21 18 { 22 19 struct list_head *head, **tail = &head; ··· 49 52 * throughout. 50 53 */ 51 54 __attribute__((nonnull(2,3,4,5))) 52 - static void merge_final(void *priv, cmp_func cmp, struct list_head *head, 55 + static void merge_final(void *priv, list_cmp_func_t cmp, struct list_head *head, 53 56 struct list_head *a, struct list_head *b) 54 57 { 55 58 struct list_head *tail = head; ··· 182 185 * 2^(k+1) - 1 (second merge of case 5 when x == 2^(k-1) - 1). 183 186 */ 184 187 __attribute__((nonnull(2,3))) 185 - void list_sort(void *priv, struct list_head *head, 186 - int (*cmp)(void *priv, struct list_head *a, 187 - struct list_head *b)) 188 + void list_sort(void *priv, struct list_head *head, list_cmp_func_t cmp) 188 189 { 189 190 struct list_head *list = head->next, *pending = NULL; 190 191 size_t count = 0; /* Count of pending */ ··· 222 227 if (likely(bits)) { 223 228 struct list_head *a = *tail, *b = a->prev; 224 229 225 - a = merge(priv, (cmp_func)cmp, b, a); 230 + a = merge(priv, cmp, b, a); 226 231 /* Install the merged result in place of the inputs */ 227 232 a->prev = b->prev; 228 233 *tail = a; ··· 244 249 245 250 if (!next) 246 251 break; 247 - list = merge(priv, (cmp_func)cmp, pending, list); 252 + list = merge(priv, cmp, pending, list); 248 253 pending = next; 249 254 } 250 255 /* The final merge, rebuilding prev links */ 251 - merge_final(priv, (cmp_func)cmp, head, pending, list); 256 + merge_final(priv, cmp, head, pending, list); 252 257 } 253 258 EXPORT_SYMBOL(list_sort);
+2 -1
lib/test_list_sort.c
··· 56 56 return 0; 57 57 } 58 58 59 - static int __init cmp(void *priv, struct list_head *a, struct list_head *b) 59 + static int __init cmp(void *priv, const struct list_head *a, 60 + const struct list_head *b) 60 61 { 61 62 struct debug_el *ela, *elb; 62 63
+2 -2
net/tipc/name_table.c
··· 397 397 * Code reused: time_after32() for the same purpose 398 398 */ 399 399 #define publication_after(pa, pb) time_after32((pa)->id, (pb)->id) 400 - static int tipc_publ_sort(void *priv, struct list_head *a, 401 - struct list_head *b) 400 + static int tipc_publ_sort(void *priv, const struct list_head *a, 401 + const struct list_head *b) 402 402 { 403 403 struct publication *pa, *pb; 404 404