Skip to content

Commit 87335b6

Browse files
melverPeter Zijlstra
authored andcommitted
security/tomoyo: Enable context analysis
Enable context analysis for security/tomoyo. This demonstrates a larger conversion to use Clang's context analysis. The benefit is additional static checking of locking rules, along with better documentation. Tomoyo makes use of several synchronization primitives, yet its clear design made it relatively straightforward to enable context analysis. One notable finding was: security/tomoyo/gc.c:664:20: error: reading variable 'write_buf' requires holding mutex '&tomoyo_io_buffer::io_sem' 664 | is_write = head->write_buf != NULL; For which Tetsuo writes: "Good catch. This should be data_race(), for tomoyo_write_control() might concurrently update head->write_buf from non-NULL to non-NULL with head->io_sem held." Signed-off-by: Marco Elver <elver@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20251219154418.3592607-35-elver@google.com
1 parent 8ec56d9 commit 87335b6

9 files changed

Lines changed: 122 additions & 49 deletions

File tree

security/tomoyo/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0
2+
CONTEXT_ANALYSIS := y
3+
24
obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
35

46
targets += builtin-policy.h

security/tomoyo/common.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt,
268268
*/
269269
static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt,
270270
...)
271+
__must_hold(&head->io_sem)
271272
{
272273
va_list args;
273274
size_t len;
@@ -416,8 +417,9 @@ static void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head,
416417
*
417418
* Returns nothing.
418419
*/
419-
static void tomoyo_print_number_union_nospace
420-
(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr)
420+
static void
421+
tomoyo_print_number_union_nospace(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr)
422+
__must_hold(&head->io_sem)
421423
{
422424
if (ptr->group) {
423425
tomoyo_set_string(head, "@");
@@ -466,6 +468,7 @@ static void tomoyo_print_number_union_nospace
466468
*/
467469
static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
468470
const struct tomoyo_number_union *ptr)
471+
__must_hold(&head->io_sem)
469472
{
470473
tomoyo_set_space(head);
471474
tomoyo_print_number_union_nospace(head, ptr);
@@ -664,6 +667,7 @@ static int tomoyo_set_mode(char *name, const char *value,
664667
* Returns 0 on success, negative value otherwise.
665668
*/
666669
static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
670+
__must_hold(&head->io_sem)
667671
{
668672
char *data = head->write_buf;
669673
unsigned int i;
@@ -719,6 +723,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
719723
* Caller prints functionality's name.
720724
*/
721725
static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
726+
__must_hold(&head->io_sem)
722727
{
723728
tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
724729
tomoyo_mode[config & 3],
@@ -734,6 +739,7 @@ static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
734739
* Returns nothing.
735740
*/
736741
static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
742+
__must_hold(&head->io_sem)
737743
{
738744
u8 index;
739745
struct tomoyo_policy_namespace *ns =
@@ -852,6 +858,7 @@ static bool tomoyo_same_manager(const struct tomoyo_acl_head *a,
852858
*/
853859
static int tomoyo_update_manager_entry(const char *manager,
854860
const bool is_delete)
861+
__must_hold_shared(&tomoyo_ss)
855862
{
856863
struct tomoyo_manager e = { };
857864
struct tomoyo_acl_param param = {
@@ -883,6 +890,8 @@ static int tomoyo_update_manager_entry(const char *manager,
883890
* Caller holds tomoyo_read_lock().
884891
*/
885892
static int tomoyo_write_manager(struct tomoyo_io_buffer *head)
893+
__must_hold_shared(&tomoyo_ss)
894+
__must_hold(&head->io_sem)
886895
{
887896
char *data = head->write_buf;
888897

@@ -901,6 +910,7 @@ static int tomoyo_write_manager(struct tomoyo_io_buffer *head)
901910
* Caller holds tomoyo_read_lock().
902911
*/
903912
static void tomoyo_read_manager(struct tomoyo_io_buffer *head)
913+
__must_hold_shared(&tomoyo_ss)
904914
{
905915
if (head->r.eof)
906916
return;
@@ -927,6 +937,7 @@ static void tomoyo_read_manager(struct tomoyo_io_buffer *head)
927937
* Caller holds tomoyo_read_lock().
928938
*/
929939
static bool tomoyo_manager(void)
940+
__must_hold_shared(&tomoyo_ss)
930941
{
931942
struct tomoyo_manager *ptr;
932943
const char *exe;
@@ -981,6 +992,8 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
981992
*/
982993
static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
983994
const char *data)
995+
__must_hold_shared(&tomoyo_ss)
996+
__must_hold(&head->io_sem)
984997
{
985998
unsigned int pid;
986999
struct tomoyo_domain_info *domain = NULL;
@@ -1051,6 +1064,7 @@ static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a,
10511064
* Caller holds tomoyo_read_lock().
10521065
*/
10531066
static int tomoyo_write_task(struct tomoyo_acl_param *param)
1067+
__must_hold_shared(&tomoyo_ss)
10541068
{
10551069
int error = -EINVAL;
10561070

@@ -1079,6 +1093,7 @@ static int tomoyo_write_task(struct tomoyo_acl_param *param)
10791093
* Caller holds tomoyo_read_lock().
10801094
*/
10811095
static int tomoyo_delete_domain(char *domainname)
1096+
__must_hold_shared(&tomoyo_ss)
10821097
{
10831098
struct tomoyo_domain_info *domain;
10841099
struct tomoyo_path_info name;
@@ -1118,6 +1133,7 @@ static int tomoyo_delete_domain(char *domainname)
11181133
static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns,
11191134
struct list_head *list, char *data,
11201135
const bool is_delete)
1136+
__must_hold_shared(&tomoyo_ss)
11211137
{
11221138
struct tomoyo_acl_param param = {
11231139
.ns = ns,
@@ -1162,6 +1178,8 @@ const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS] = {
11621178
* Caller holds tomoyo_read_lock().
11631179
*/
11641180
static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
1181+
__must_hold_shared(&tomoyo_ss)
1182+
__must_hold(&head->io_sem)
11651183
{
11661184
char *data = head->write_buf;
11671185
struct tomoyo_policy_namespace *ns;
@@ -1223,6 +1241,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
12231241
*/
12241242
static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
12251243
const struct tomoyo_condition *cond)
1244+
__must_hold(&head->io_sem)
12261245
{
12271246
switch (head->r.cond_step) {
12281247
case 0:
@@ -1364,6 +1383,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
13641383
*/
13651384
static void tomoyo_set_group(struct tomoyo_io_buffer *head,
13661385
const char *category)
1386+
__must_hold(&head->io_sem)
13671387
{
13681388
if (head->type == TOMOYO_EXCEPTIONPOLICY) {
13691389
tomoyo_print_namespace(head);
@@ -1383,6 +1403,7 @@ static void tomoyo_set_group(struct tomoyo_io_buffer *head,
13831403
*/
13841404
static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
13851405
struct tomoyo_acl_info *acl)
1406+
__must_hold(&head->io_sem)
13861407
{
13871408
const u8 acl_type = acl->type;
13881409
bool first = true;
@@ -1588,6 +1609,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
15881609
*/
15891610
static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head,
15901611
struct list_head *list)
1612+
__must_hold_shared(&tomoyo_ss)
1613+
__must_hold(&head->io_sem)
15911614
{
15921615
list_for_each_cookie(head->r.acl, list) {
15931616
struct tomoyo_acl_info *ptr =
@@ -1608,6 +1631,8 @@ static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head,
16081631
* Caller holds tomoyo_read_lock().
16091632
*/
16101633
static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
1634+
__must_hold_shared(&tomoyo_ss)
1635+
__must_hold(&head->io_sem)
16111636
{
16121637
if (head->r.eof)
16131638
return;
@@ -1686,6 +1711,7 @@ static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
16861711
* using read()/write() interface rather than sysctl() interface.
16871712
*/
16881713
static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
1714+
__must_hold(&head->io_sem)
16891715
{
16901716
char *buf = head->write_buf;
16911717
bool global_pid = false;
@@ -1746,6 +1772,8 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
17461772
* Caller holds tomoyo_read_lock().
17471773
*/
17481774
static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
1775+
__must_hold_shared(&tomoyo_ss)
1776+
__must_hold(&head->io_sem)
17491777
{
17501778
const bool is_delete = head->w.is_delete;
17511779
struct tomoyo_acl_param param = {
@@ -1787,6 +1815,8 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
17871815
* Caller holds tomoyo_read_lock().
17881816
*/
17891817
static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
1818+
__must_hold_shared(&tomoyo_ss)
1819+
__must_hold(&head->io_sem)
17901820
{
17911821
struct tomoyo_policy_namespace *ns =
17921822
container_of(head->r.ns, typeof(*ns), namespace_list);
@@ -1846,6 +1876,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
18461876
* Caller holds tomoyo_read_lock().
18471877
*/
18481878
static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
1879+
__must_hold_shared(&tomoyo_ss)
18491880
{
18501881
struct tomoyo_policy_namespace *ns =
18511882
container_of(head->r.ns, typeof(*ns), namespace_list);
@@ -1906,6 +1937,8 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
19061937
* Caller holds tomoyo_read_lock().
19071938
*/
19081939
static void tomoyo_read_exception(struct tomoyo_io_buffer *head)
1940+
__must_hold_shared(&tomoyo_ss)
1941+
__must_hold(&head->io_sem)
19091942
{
19101943
struct tomoyo_policy_namespace *ns =
19111944
container_of(head->r.ns, typeof(*ns), namespace_list);
@@ -2097,6 +2130,7 @@ static void tomoyo_patternize_path(char *buffer, const int len, char *entry)
20972130
* Returns nothing.
20982131
*/
20992132
static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
2133+
__must_hold_shared(&tomoyo_ss)
21002134
{
21012135
char *buffer;
21022136
char *realpath = NULL;
@@ -2301,6 +2335,7 @@ static __poll_t tomoyo_poll_query(struct file *file, poll_table *wait)
23012335
* @head: Pointer to "struct tomoyo_io_buffer".
23022336
*/
23032337
static void tomoyo_read_query(struct tomoyo_io_buffer *head)
2338+
__must_hold(&head->io_sem)
23042339
{
23052340
struct list_head *tmp;
23062341
unsigned int pos = 0;
@@ -2362,6 +2397,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
23622397
* Returns 0 on success, -EINVAL otherwise.
23632398
*/
23642399
static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
2400+
__must_hold(&head->io_sem)
23652401
{
23662402
char *data = head->write_buf;
23672403
struct list_head *tmp;
@@ -2401,6 +2437,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
24012437
* Returns version information.
24022438
*/
24032439
static void tomoyo_read_version(struct tomoyo_io_buffer *head)
2440+
__must_hold(&head->io_sem)
24042441
{
24052442
if (!head->r.eof) {
24062443
tomoyo_io_printf(head, "2.6.0");
@@ -2449,6 +2486,7 @@ void tomoyo_update_stat(const u8 index)
24492486
* Returns nothing.
24502487
*/
24512488
static void tomoyo_read_stat(struct tomoyo_io_buffer *head)
2489+
__must_hold(&head->io_sem)
24522490
{
24532491
u8 i;
24542492
unsigned int total = 0;
@@ -2493,6 +2531,7 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head)
24932531
* Returns 0.
24942532
*/
24952533
static int tomoyo_write_stat(struct tomoyo_io_buffer *head)
2534+
__must_hold(&head->io_sem)
24962535
{
24972536
char *data = head->write_buf;
24982537
u8 i;
@@ -2717,6 +2756,8 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
27172756
* Caller holds tomoyo_read_lock().
27182757
*/
27192758
static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line)
2759+
__must_hold_shared(&tomoyo_ss)
2760+
__must_hold(&head->io_sem)
27202761
{
27212762
/* Delete request? */
27222763
head->w.is_delete = !strncmp(line, "delete ", 7);
@@ -2969,8 +3010,11 @@ void __init tomoyo_load_builtin_policy(void)
29693010
break;
29703011
*end = '\0';
29713012
tomoyo_normalize_line(start);
2972-
head.write_buf = start;
2973-
tomoyo_parse_policy(&head, start);
3013+
/* head is stack-local and not shared. */
3014+
context_unsafe(
3015+
head.write_buf = start;
3016+
tomoyo_parse_policy(&head, start);
3017+
);
29743018
start = end + 1;
29753019
}
29763020
}

0 commit comments

Comments
 (0)