hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/security/tomoyo/util.c
....@@ -91,6 +91,7 @@
9191 void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp)
9292 {
9393 struct tm tm;
94
+
9495 time64_to_tm(time64, 0, &tm);
9596 stamp->sec = tm.tm_sec;
9697 stamp->min = tm.tm_min;
....@@ -106,13 +107,14 @@
106107 * @string: String representation for permissions in foo/bar/buz format.
107108 * @keyword: Keyword to find from @string/
108109 *
109
- * Returns ture if @keyword was found in @string, false otherwise.
110
+ * Returns true if @keyword was found in @string, false otherwise.
110111 *
111112 * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
112113 */
113114 bool tomoyo_permstr(const char *string, const char *keyword)
114115 {
115116 const char *cp = strstr(string, keyword);
117
+
116118 if (cp)
117119 return cp == string || *(cp - 1) == '/';
118120 return false;
....@@ -132,6 +134,7 @@
132134 {
133135 char *pos = param->data;
134136 char *del = strchr(pos, ' ');
137
+
135138 if (del)
136139 *del++ = '\0';
137140 else
....@@ -139,6 +142,8 @@
139142 param->data = del;
140143 return pos;
141144 }
145
+
146
+static bool tomoyo_correct_path2(const char *filename, const size_t len);
142147
143148 /**
144149 * tomoyo_get_domainname - Read a domainname from a line.
....@@ -152,11 +157,12 @@
152157 {
153158 char *start = param->data;
154159 char *pos = start;
160
+
155161 while (*pos) {
156
- if (*pos++ != ' ' || *pos++ == '/')
162
+ if (*pos++ != ' ' ||
163
+ tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos))
157164 continue;
158
- pos -= 2;
159
- *pos++ = '\0';
165
+ *(pos - 1) = '\0';
160166 break;
161167 }
162168 param->data = pos;
....@@ -181,8 +187,10 @@
181187 const char *cp = *str;
182188 char *ep;
183189 int base = 10;
190
+
184191 if (*cp == '0') {
185192 char c = *(cp + 1);
193
+
186194 if (c == 'x' || c == 'X') {
187195 base = 16;
188196 cp += 2;
....@@ -240,6 +248,7 @@
240248 struct tomoyo_name_union *ptr)
241249 {
242250 char *filename;
251
+
243252 if (param->data[0] == '@') {
244253 param->data++;
245254 ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
....@@ -266,6 +275,7 @@
266275 char *data;
267276 u8 type;
268277 unsigned long v;
278
+
269279 memset(ptr, 0, sizeof(*ptr));
270280 if (param->data[0] == '@') {
271281 param->data++;
....@@ -429,6 +439,7 @@
429439 unsigned char c;
430440 unsigned char d;
431441 unsigned char e;
442
+
432443 if (!len)
433444 goto out;
434445 while (len--) {
....@@ -505,6 +516,22 @@
505516 }
506517
507518 /**
519
+ * tomoyo_correct_path2 - Check whether the given pathname follows the naming rules.
520
+ *
521
+ * @filename: The pathname to check.
522
+ * @len: Length of @filename.
523
+ *
524
+ * Returns true if @filename follows the naming rules, false otherwise.
525
+ */
526
+static bool tomoyo_correct_path2(const char *filename, const size_t len)
527
+{
528
+ const char *cp1 = memchr(filename, '/', len);
529
+ const char *cp2 = memchr(filename, '.', len);
530
+
531
+ return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len);
532
+}
533
+
534
+/**
508535 * tomoyo_correct_path - Validate a pathname.
509536 *
510537 * @filename: The pathname to check.
....@@ -514,7 +541,7 @@
514541 */
515542 bool tomoyo_correct_path(const char *filename)
516543 {
517
- return *filename == '/' && tomoyo_correct_word(filename);
544
+ return tomoyo_correct_path2(filename, strlen(filename));
518545 }
519546
520547 /**
....@@ -533,10 +560,10 @@
533560 return true;
534561 while (1) {
535562 const unsigned char *cp = strchr(domainname, ' ');
563
+
536564 if (!cp)
537565 break;
538
- if (*domainname != '/' ||
539
- !tomoyo_correct_word2(domainname, cp - domainname))
566
+ if (!tomoyo_correct_path2(domainname, cp - domainname))
540567 return false;
541568 domainname = cp + 1;
542569 }
....@@ -554,6 +581,7 @@
554581 {
555582 const unsigned char *cp;
556583 int len;
584
+
557585 if (*buffer != '<')
558586 return false;
559587 cp = strchr(buffer, ' ');
....@@ -583,7 +611,8 @@
583611
584612 name.name = domainname;
585613 tomoyo_fill_path_info(&name);
586
- list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
614
+ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
615
+ srcu_read_lock_held(&tomoyo_ss)) {
587616 if (!domain->is_deleted &&
588617 !tomoyo_pathcmp(&name, domain->domainname))
589618 return domain;
....@@ -668,6 +697,9 @@
668697 {
669698 while (filename < filename_end && pattern < pattern_end) {
670699 char c;
700
+ int i;
701
+ int j;
702
+
671703 if (*pattern != '\\') {
672704 if (*filename++ != *pattern++)
673705 return false;
....@@ -676,8 +708,6 @@
676708 c = *filename;
677709 pattern++;
678710 switch (*pattern) {
679
- int i;
680
- int j;
681711 case '?':
682712 if (c == '/') {
683713 return false;
....@@ -985,6 +1015,7 @@
9851015 struct tomoyo_domain_info *domain, const u8 index)
9861016 {
9871017 u8 profile;
1018
+
9881019 memset(r, 0, sizeof(*r));
9891020 if (!domain)
9901021 domain = tomoyo_domain();
....@@ -1015,35 +1046,38 @@
10151046 return false;
10161047 if (!domain)
10171048 return true;
1018
- list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1049
+ if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED]))
1050
+ return false;
1051
+ list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
1052
+ srcu_read_lock_held(&tomoyo_ss)) {
10191053 u16 perm;
1020
- u8 i;
1054
+
10211055 if (ptr->is_deleted)
10221056 continue;
1057
+ /*
1058
+ * Reading perm bitmap might race with tomoyo_merge_*() because
1059
+ * caller does not hold tomoyo_policy_lock mutex. But exceeding
1060
+ * max_learning_entry parameter by a few entries does not harm.
1061
+ */
10231062 switch (ptr->type) {
10241063 case TOMOYO_TYPE_PATH_ACL:
1025
- perm = container_of(ptr, struct tomoyo_path_acl, head)
1026
- ->perm;
1064
+ perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm);
10271065 break;
10281066 case TOMOYO_TYPE_PATH2_ACL:
1029
- perm = container_of(ptr, struct tomoyo_path2_acl, head)
1030
- ->perm;
1067
+ perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm);
10311068 break;
10321069 case TOMOYO_TYPE_PATH_NUMBER_ACL:
1033
- perm = container_of(ptr, struct tomoyo_path_number_acl,
1034
- head)->perm;
1070
+ perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head)
1071
+ ->perm);
10351072 break;
10361073 case TOMOYO_TYPE_MKDEV_ACL:
1037
- perm = container_of(ptr, struct tomoyo_mkdev_acl,
1038
- head)->perm;
1074
+ perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
10391075 break;
10401076 case TOMOYO_TYPE_INET_ACL:
1041
- perm = container_of(ptr, struct tomoyo_inet_acl,
1042
- head)->perm;
1077
+ perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm);
10431078 break;
10441079 case TOMOYO_TYPE_UNIX_ACL:
1045
- perm = container_of(ptr, struct tomoyo_unix_acl,
1046
- head)->perm;
1080
+ perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm);
10471081 break;
10481082 case TOMOYO_TYPE_MANUAL_TASK_ACL:
10491083 perm = 0;
....@@ -1051,20 +1085,17 @@
10511085 default:
10521086 perm = 1;
10531087 }
1054
- for (i = 0; i < 16; i++)
1055
- if (perm & (1 << i))
1056
- count++;
1088
+ count += hweight16(perm);
10571089 }
10581090 if (count < tomoyo_profile(domain->ns, domain->profile)->
10591091 pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
10601092 return true;
1061
- if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) {
1062
- domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true;
1063
- /* r->granted = false; */
1064
- tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
1065
- printk(KERN_WARNING "WARNING: "
1066
- "Domain '%s' has too many ACLs to hold. "
1067
- "Stopped learning mode.\n", domain->domainname->name);
1068
- }
1093
+ WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true);
1094
+ /* r->granted = false; */
1095
+ tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
1096
+#ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
1097
+ pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
1098
+ domain->domainname->name);
1099
+#endif
10691100 return false;
10701101 }