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

tomoyo: ignore data race while checking quota

syzbot is reporting that tomoyo's quota check is racy [1]. But this check
is tolerant of some degree of inaccuracy. Thus, teach KCSAN to ignore
this data race.

[1] https://syzkaller.appspot.com/bug?id=999533deec7ba6337f8aa25d8bd1a4d5f7e50476

Reported-by: syzbot <syzbot+0789a72b46fd91431bd8@syzkaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

+24 -24
+8 -8
security/tomoyo/file.c
··· 362 362 { 363 363 u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) 364 364 ->perm; 365 - u16 perm = *a_perm; 365 + u16 perm = READ_ONCE(*a_perm); 366 366 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; 367 367 368 368 if (is_delete) 369 369 perm &= ~b_perm; 370 370 else 371 371 perm |= b_perm; 372 - *a_perm = perm; 372 + WRITE_ONCE(*a_perm, perm); 373 373 return !perm; 374 374 } 375 375 ··· 437 437 { 438 438 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, 439 439 head)->perm; 440 - u8 perm = *a_perm; 440 + u8 perm = READ_ONCE(*a_perm); 441 441 const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) 442 442 ->perm; 443 443 ··· 445 445 perm &= ~b_perm; 446 446 else 447 447 perm |= b_perm; 448 - *a_perm = perm; 448 + WRITE_ONCE(*a_perm, perm); 449 449 return !perm; 450 450 } 451 451 ··· 517 517 { 518 518 u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) 519 519 ->perm; 520 - u8 perm = *a_perm; 520 + u8 perm = READ_ONCE(*a_perm); 521 521 const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; 522 522 523 523 if (is_delete) 524 524 perm &= ~b_perm; 525 525 else 526 526 perm |= b_perm; 527 - *a_perm = perm; 527 + WRITE_ONCE(*a_perm, perm); 528 528 return !perm; 529 529 } 530 530 ··· 655 655 { 656 656 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, 657 657 head)->perm; 658 - u8 perm = *a_perm; 658 + u8 perm = READ_ONCE(*a_perm); 659 659 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) 660 660 ->perm; 661 661 ··· 663 663 perm &= ~b_perm; 664 664 else 665 665 perm |= b_perm; 666 - *a_perm = perm; 666 + WRITE_ONCE(*a_perm, perm); 667 667 return !perm; 668 668 } 669 669
+4 -4
security/tomoyo/network.c
··· 233 233 { 234 234 u8 * const a_perm = 235 235 &container_of(a, struct tomoyo_inet_acl, head)->perm; 236 - u8 perm = *a_perm; 236 + u8 perm = READ_ONCE(*a_perm); 237 237 const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm; 238 238 239 239 if (is_delete) 240 240 perm &= ~b_perm; 241 241 else 242 242 perm |= b_perm; 243 - *a_perm = perm; 243 + WRITE_ONCE(*a_perm, perm); 244 244 return !perm; 245 245 } 246 246 ··· 259 259 { 260 260 u8 * const a_perm = 261 261 &container_of(a, struct tomoyo_unix_acl, head)->perm; 262 - u8 perm = *a_perm; 262 + u8 perm = READ_ONCE(*a_perm); 263 263 const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm; 264 264 265 265 if (is_delete) 266 266 perm &= ~b_perm; 267 267 else 268 268 perm |= b_perm; 269 - *a_perm = perm; 269 + WRITE_ONCE(*a_perm, perm); 270 270 return !perm; 271 271 } 272 272
+12 -12
security/tomoyo/util.c
··· 1058 1058 1059 1059 if (ptr->is_deleted) 1060 1060 continue; 1061 + /* 1062 + * Reading perm bitmap might race with tomoyo_merge_*() because 1063 + * caller does not hold tomoyo_policy_lock mutex. But exceeding 1064 + * max_learning_entry parameter by a few entries does not harm. 1065 + */ 1061 1066 switch (ptr->type) { 1062 1067 case TOMOYO_TYPE_PATH_ACL: 1063 - perm = container_of(ptr, struct tomoyo_path_acl, head) 1064 - ->perm; 1068 + data_race(perm = container_of(ptr, struct tomoyo_path_acl, head)->perm); 1065 1069 break; 1066 1070 case TOMOYO_TYPE_PATH2_ACL: 1067 - perm = container_of(ptr, struct tomoyo_path2_acl, head) 1068 - ->perm; 1071 + data_race(perm = container_of(ptr, struct tomoyo_path2_acl, head)->perm); 1069 1072 break; 1070 1073 case TOMOYO_TYPE_PATH_NUMBER_ACL: 1071 - perm = container_of(ptr, struct tomoyo_path_number_acl, 1072 - head)->perm; 1074 + data_race(perm = container_of(ptr, struct tomoyo_path_number_acl, head) 1075 + ->perm); 1073 1076 break; 1074 1077 case TOMOYO_TYPE_MKDEV_ACL: 1075 - perm = container_of(ptr, struct tomoyo_mkdev_acl, 1076 - head)->perm; 1078 + data_race(perm = container_of(ptr, struct tomoyo_mkdev_acl, head)->perm); 1077 1079 break; 1078 1080 case TOMOYO_TYPE_INET_ACL: 1079 - perm = container_of(ptr, struct tomoyo_inet_acl, 1080 - head)->perm; 1081 + data_race(perm = container_of(ptr, struct tomoyo_inet_acl, head)->perm); 1081 1082 break; 1082 1083 case TOMOYO_TYPE_UNIX_ACL: 1083 - perm = container_of(ptr, struct tomoyo_unix_acl, 1084 - head)->perm; 1084 + data_race(perm = container_of(ptr, struct tomoyo_unix_acl, head)->perm); 1085 1085 break; 1086 1086 case TOMOYO_TYPE_MANUAL_TASK_ACL: 1087 1087 perm = 0;