0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/slab.h>
0009 #include <linux/rculist.h>
0010
0011 #include "common.h"
0012
0013
0014 DEFINE_MUTEX(tomoyo_policy_lock);
0015
0016
0017 bool tomoyo_policy_loaded;
0018
0019
0020
0021
0022
0023 const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
0024
0025 [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE,
0026 [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE,
0027 [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE,
0028 [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE,
0029 [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE,
0030 [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE,
0031 [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE,
0032 [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE,
0033 [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE,
0034 [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE,
0035 [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE,
0036 [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE,
0037 [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE,
0038 [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE,
0039 [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE,
0040 [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE,
0041 [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE,
0042 [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE,
0043 [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE,
0044 [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE,
0045 [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE,
0046 [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE,
0047 [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
0048
0049 [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] =
0050 TOMOYO_MAC_CATEGORY_NETWORK,
0051 [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] =
0052 TOMOYO_MAC_CATEGORY_NETWORK,
0053 [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] =
0054 TOMOYO_MAC_CATEGORY_NETWORK,
0055 [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] =
0056 TOMOYO_MAC_CATEGORY_NETWORK,
0057 [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] =
0058 TOMOYO_MAC_CATEGORY_NETWORK,
0059 [TOMOYO_MAC_NETWORK_INET_RAW_BIND] =
0060 TOMOYO_MAC_CATEGORY_NETWORK,
0061 [TOMOYO_MAC_NETWORK_INET_RAW_SEND] =
0062 TOMOYO_MAC_CATEGORY_NETWORK,
0063 [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] =
0064 TOMOYO_MAC_CATEGORY_NETWORK,
0065 [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] =
0066 TOMOYO_MAC_CATEGORY_NETWORK,
0067 [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] =
0068 TOMOYO_MAC_CATEGORY_NETWORK,
0069 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] =
0070 TOMOYO_MAC_CATEGORY_NETWORK,
0071 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] =
0072 TOMOYO_MAC_CATEGORY_NETWORK,
0073 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] =
0074 TOMOYO_MAC_CATEGORY_NETWORK,
0075 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] =
0076 TOMOYO_MAC_CATEGORY_NETWORK,
0077 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] =
0078 TOMOYO_MAC_CATEGORY_NETWORK,
0079
0080 [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC,
0081 };
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp)
0092 {
0093 struct tm tm;
0094
0095 time64_to_tm(time64, 0, &tm);
0096 stamp->sec = tm.tm_sec;
0097 stamp->min = tm.tm_min;
0098 stamp->hour = tm.tm_hour;
0099 stamp->day = tm.tm_mday;
0100 stamp->month = tm.tm_mon + 1;
0101 stamp->year = tm.tm_year + 1900;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 bool tomoyo_permstr(const char *string, const char *keyword)
0115 {
0116 const char *cp = strstr(string, keyword);
0117
0118 if (cp)
0119 return cp == string || *(cp - 1) == '/';
0120 return false;
0121 }
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 char *tomoyo_read_token(struct tomoyo_acl_param *param)
0134 {
0135 char *pos = param->data;
0136 char *del = strchr(pos, ' ');
0137
0138 if (del)
0139 *del++ = '\0';
0140 else
0141 del = pos + strlen(pos);
0142 param->data = del;
0143 return pos;
0144 }
0145
0146 static bool tomoyo_correct_path2(const char *filename, const size_t len);
0147
0148
0149
0150
0151
0152
0153
0154
0155 const struct tomoyo_path_info *tomoyo_get_domainname
0156 (struct tomoyo_acl_param *param)
0157 {
0158 char *start = param->data;
0159 char *pos = start;
0160
0161 while (*pos) {
0162 if (*pos++ != ' ' ||
0163 tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos))
0164 continue;
0165 *(pos - 1) = '\0';
0166 break;
0167 }
0168 param->data = pos;
0169 if (tomoyo_correct_domain(start))
0170 return tomoyo_get_name(start);
0171 return NULL;
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 u8 tomoyo_parse_ulong(unsigned long *result, char **str)
0186 {
0187 const char *cp = *str;
0188 char *ep;
0189 int base = 10;
0190
0191 if (*cp == '0') {
0192 char c = *(cp + 1);
0193
0194 if (c == 'x' || c == 'X') {
0195 base = 16;
0196 cp += 2;
0197 } else if (c >= '0' && c <= '7') {
0198 base = 8;
0199 cp++;
0200 }
0201 }
0202 *result = simple_strtoul(cp, &ep, base);
0203 if (cp == ep)
0204 return TOMOYO_VALUE_TYPE_INVALID;
0205 *str = ep;
0206 switch (base) {
0207 case 16:
0208 return TOMOYO_VALUE_TYPE_HEXADECIMAL;
0209 case 8:
0210 return TOMOYO_VALUE_TYPE_OCTAL;
0211 default:
0212 return TOMOYO_VALUE_TYPE_DECIMAL;
0213 }
0214 }
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 void tomoyo_print_ulong(char *buffer, const int buffer_len,
0227 const unsigned long value, const u8 type)
0228 {
0229 if (type == TOMOYO_VALUE_TYPE_DECIMAL)
0230 snprintf(buffer, buffer_len, "%lu", value);
0231 else if (type == TOMOYO_VALUE_TYPE_OCTAL)
0232 snprintf(buffer, buffer_len, "0%lo", value);
0233 else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
0234 snprintf(buffer, buffer_len, "0x%lX", value);
0235 else
0236 snprintf(buffer, buffer_len, "type(%u)", type);
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
0248 struct tomoyo_name_union *ptr)
0249 {
0250 char *filename;
0251
0252 if (param->data[0] == '@') {
0253 param->data++;
0254 ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
0255 return ptr->group != NULL;
0256 }
0257 filename = tomoyo_read_token(param);
0258 if (!tomoyo_correct_word(filename))
0259 return false;
0260 ptr->filename = tomoyo_get_name(filename);
0261 return ptr->filename != NULL;
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
0273 struct tomoyo_number_union *ptr)
0274 {
0275 char *data;
0276 u8 type;
0277 unsigned long v;
0278
0279 memset(ptr, 0, sizeof(*ptr));
0280 if (param->data[0] == '@') {
0281 param->data++;
0282 ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
0283 return ptr->group != NULL;
0284 }
0285 data = tomoyo_read_token(param);
0286 type = tomoyo_parse_ulong(&v, &data);
0287 if (type == TOMOYO_VALUE_TYPE_INVALID)
0288 return false;
0289 ptr->values[0] = v;
0290 ptr->value_type[0] = type;
0291 if (!*data) {
0292 ptr->values[1] = v;
0293 ptr->value_type[1] = type;
0294 return true;
0295 }
0296 if (*data++ != '-')
0297 return false;
0298 type = tomoyo_parse_ulong(&v, &data);
0299 if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
0300 return false;
0301 ptr->values[1] = v;
0302 ptr->value_type[1] = type;
0303 return true;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 static inline bool tomoyo_byte_range(const char *str)
0317 {
0318 return *str >= '0' && *str++ <= '3' &&
0319 *str >= '0' && *str++ <= '7' &&
0320 *str >= '0' && *str <= '7';
0321 }
0322
0323
0324
0325
0326
0327
0328
0329
0330 static inline bool tomoyo_alphabet_char(const char c)
0331 {
0332 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
0333 }
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
0345 {
0346 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356 static inline bool tomoyo_valid(const unsigned char c)
0357 {
0358 return c > ' ' && c < 127;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368 static inline bool tomoyo_invalid(const unsigned char c)
0369 {
0370 return c && (c <= ' ' || c >= 127);
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 bool tomoyo_str_starts(char **src, const char *find)
0385 {
0386 const int len = strlen(find);
0387 char *tmp = *src;
0388
0389 if (strncmp(tmp, find, len))
0390 return false;
0391 tmp += len;
0392 *src = tmp;
0393 return true;
0394 }
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 void tomoyo_normalize_line(unsigned char *buffer)
0407 {
0408 unsigned char *sp = buffer;
0409 unsigned char *dp = buffer;
0410 bool first = true;
0411
0412 while (tomoyo_invalid(*sp))
0413 sp++;
0414 while (*sp) {
0415 if (!first)
0416 *dp++ = ' ';
0417 first = false;
0418 while (tomoyo_valid(*sp))
0419 *dp++ = *sp++;
0420 while (tomoyo_invalid(*sp))
0421 sp++;
0422 }
0423 *dp = '\0';
0424 }
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 static bool tomoyo_correct_word2(const char *string, size_t len)
0436 {
0437 u8 recursion = 20;
0438 const char *const start = string;
0439 bool in_repetition = false;
0440
0441 if (!len)
0442 goto out;
0443 while (len--) {
0444 unsigned char c = *string++;
0445
0446 if (c == '\\') {
0447 if (!len--)
0448 goto out;
0449 c = *string++;
0450 if (c >= '0' && c <= '3') {
0451 unsigned char d;
0452 unsigned char e;
0453
0454 if (!len-- || !len--)
0455 goto out;
0456 d = *string++;
0457 e = *string++;
0458 if (d < '0' || d > '7' || e < '0' || e > '7')
0459 goto out;
0460 c = tomoyo_make_byte(c, d, e);
0461 if (c <= ' ' || c >= 127)
0462 continue;
0463 goto out;
0464 }
0465 switch (c) {
0466 case '\\':
0467 case '+':
0468 case '?':
0469 case 'x':
0470 case 'a':
0471 case '-':
0472 continue;
0473 }
0474 if (!recursion--)
0475 goto out;
0476 switch (c) {
0477 case '*':
0478 case '@':
0479 case '$':
0480 case 'X':
0481 case 'A':
0482 continue;
0483 case '{':
0484 if (string - 3 < start || *(string - 3) != '/')
0485 goto out;
0486 in_repetition = true;
0487 continue;
0488 case '}':
0489 if (*string != '/')
0490 goto out;
0491 if (!in_repetition)
0492 goto out;
0493 in_repetition = false;
0494 continue;
0495 }
0496 goto out;
0497 } else if (in_repetition && c == '/') {
0498 goto out;
0499 } else if (c <= ' ' || c >= 127) {
0500 goto out;
0501 }
0502 }
0503 if (in_repetition)
0504 goto out;
0505 return true;
0506 out:
0507 return false;
0508 }
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518 bool tomoyo_correct_word(const char *string)
0519 {
0520 return tomoyo_correct_word2(string, strlen(string));
0521 }
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531 static bool tomoyo_correct_path2(const char *filename, const size_t len)
0532 {
0533 const char *cp1 = memchr(filename, '/', len);
0534 const char *cp2 = memchr(filename, '.', len);
0535
0536 return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len);
0537 }
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547 bool tomoyo_correct_path(const char *filename)
0548 {
0549 return tomoyo_correct_path2(filename, strlen(filename));
0550 }
0551
0552
0553
0554
0555
0556
0557
0558
0559 bool tomoyo_correct_domain(const unsigned char *domainname)
0560 {
0561 if (!domainname || !tomoyo_domain_def(domainname))
0562 return false;
0563 domainname = strchr(domainname, ' ');
0564 if (!domainname++)
0565 return true;
0566 while (1) {
0567 const unsigned char *cp = strchr(domainname, ' ');
0568
0569 if (!cp)
0570 break;
0571 if (!tomoyo_correct_path2(domainname, cp - domainname))
0572 return false;
0573 domainname = cp + 1;
0574 }
0575 return tomoyo_correct_path(domainname);
0576 }
0577
0578
0579
0580
0581
0582
0583
0584
0585 bool tomoyo_domain_def(const unsigned char *buffer)
0586 {
0587 const unsigned char *cp;
0588 int len;
0589
0590 if (*buffer != '<')
0591 return false;
0592 cp = strchr(buffer, ' ');
0593 if (!cp)
0594 len = strlen(buffer);
0595 else
0596 len = cp - buffer;
0597 if (buffer[len - 1] != '>' ||
0598 !tomoyo_correct_word2(buffer + 1, len - 2))
0599 return false;
0600 return true;
0601 }
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
0613 {
0614 struct tomoyo_domain_info *domain;
0615 struct tomoyo_path_info name;
0616
0617 name.name = domainname;
0618 tomoyo_fill_path_info(&name);
0619 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
0620 srcu_read_lock_held(&tomoyo_ss)) {
0621 if (!domain->is_deleted &&
0622 !tomoyo_pathcmp(&name, domain->domainname))
0623 return domain;
0624 }
0625 return NULL;
0626 }
0627
0628
0629
0630
0631
0632
0633
0634
0635 static int tomoyo_const_part_length(const char *filename)
0636 {
0637 char c;
0638 int len = 0;
0639
0640 if (!filename)
0641 return 0;
0642 while ((c = *filename++) != '\0') {
0643 if (c != '\\') {
0644 len++;
0645 continue;
0646 }
0647 c = *filename++;
0648 switch (c) {
0649 case '\\':
0650 len += 2;
0651 continue;
0652 case '0':
0653 case '1':
0654 case '2':
0655 case '3':
0656 c = *filename++;
0657 if (c < '0' || c > '7')
0658 break;
0659 c = *filename++;
0660 if (c < '0' || c > '7')
0661 break;
0662 len += 4;
0663 continue;
0664 }
0665 break;
0666 }
0667 return len;
0668 }
0669
0670
0671
0672
0673
0674
0675
0676
0677 void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
0678 {
0679 const char *name = ptr->name;
0680 const int len = strlen(name);
0681
0682 ptr->const_len = tomoyo_const_part_length(name);
0683 ptr->is_dir = len && (name[len - 1] == '/');
0684 ptr->is_patterned = (ptr->const_len < len);
0685 ptr->hash = full_name_hash(NULL, name, len);
0686 }
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 static bool tomoyo_file_matches_pattern2(const char *filename,
0699 const char *filename_end,
0700 const char *pattern,
0701 const char *pattern_end)
0702 {
0703 while (filename < filename_end && pattern < pattern_end) {
0704 char c;
0705 int i;
0706 int j;
0707
0708 if (*pattern != '\\') {
0709 if (*filename++ != *pattern++)
0710 return false;
0711 continue;
0712 }
0713 c = *filename;
0714 pattern++;
0715 switch (*pattern) {
0716 case '?':
0717 if (c == '/') {
0718 return false;
0719 } else if (c == '\\') {
0720 if (filename[1] == '\\')
0721 filename++;
0722 else if (tomoyo_byte_range(filename + 1))
0723 filename += 3;
0724 else
0725 return false;
0726 }
0727 break;
0728 case '\\':
0729 if (c != '\\')
0730 return false;
0731 if (*++filename != '\\')
0732 return false;
0733 break;
0734 case '+':
0735 if (!isdigit(c))
0736 return false;
0737 break;
0738 case 'x':
0739 if (!isxdigit(c))
0740 return false;
0741 break;
0742 case 'a':
0743 if (!tomoyo_alphabet_char(c))
0744 return false;
0745 break;
0746 case '0':
0747 case '1':
0748 case '2':
0749 case '3':
0750 if (c == '\\' && tomoyo_byte_range(filename + 1)
0751 && strncmp(filename + 1, pattern, 3) == 0) {
0752 filename += 3;
0753 pattern += 2;
0754 break;
0755 }
0756 return false;
0757 case '*':
0758 case '@':
0759 for (i = 0; i <= filename_end - filename; i++) {
0760 if (tomoyo_file_matches_pattern2(
0761 filename + i, filename_end,
0762 pattern + 1, pattern_end))
0763 return true;
0764 c = filename[i];
0765 if (c == '.' && *pattern == '@')
0766 break;
0767 if (c != '\\')
0768 continue;
0769 if (filename[i + 1] == '\\')
0770 i++;
0771 else if (tomoyo_byte_range(filename + i + 1))
0772 i += 3;
0773 else
0774 break;
0775 }
0776 return false;
0777 default:
0778 j = 0;
0779 c = *pattern;
0780 if (c == '$') {
0781 while (isdigit(filename[j]))
0782 j++;
0783 } else if (c == 'X') {
0784 while (isxdigit(filename[j]))
0785 j++;
0786 } else if (c == 'A') {
0787 while (tomoyo_alphabet_char(filename[j]))
0788 j++;
0789 }
0790 for (i = 1; i <= j; i++) {
0791 if (tomoyo_file_matches_pattern2(
0792 filename + i, filename_end,
0793 pattern + 1, pattern_end))
0794 return true;
0795 }
0796 return false;
0797 }
0798 filename++;
0799 pattern++;
0800 }
0801 while (*pattern == '\\' &&
0802 (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
0803 pattern += 2;
0804 return filename == filename_end && pattern == pattern_end;
0805 }
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817 static bool tomoyo_file_matches_pattern(const char *filename,
0818 const char *filename_end,
0819 const char *pattern,
0820 const char *pattern_end)
0821 {
0822 const char *pattern_start = pattern;
0823 bool first = true;
0824 bool result;
0825
0826 while (pattern < pattern_end - 1) {
0827
0828 if (*pattern++ != '\\' || *pattern++ != '-')
0829 continue;
0830 result = tomoyo_file_matches_pattern2(filename,
0831 filename_end,
0832 pattern_start,
0833 pattern - 2);
0834 if (first)
0835 result = !result;
0836 if (result)
0837 return false;
0838 first = false;
0839 pattern_start = pattern;
0840 }
0841 result = tomoyo_file_matches_pattern2(filename, filename_end,
0842 pattern_start, pattern_end);
0843 return first ? result : !result;
0844 }
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854 static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
0855 {
0856 const char *f_delimiter;
0857 const char *p_delimiter;
0858
0859 while (*f && *p) {
0860 f_delimiter = strchr(f, '/');
0861 if (!f_delimiter)
0862 f_delimiter = f + strlen(f);
0863 p_delimiter = strchr(p, '/');
0864 if (!p_delimiter)
0865 p_delimiter = p + strlen(p);
0866 if (*p == '\\' && *(p + 1) == '{')
0867 goto recursive;
0868 if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
0869 p_delimiter))
0870 return false;
0871 f = f_delimiter;
0872 if (*f)
0873 f++;
0874 p = p_delimiter;
0875 if (*p)
0876 p++;
0877 }
0878
0879 while (*p == '\\' &&
0880 (*(p + 1) == '*' || *(p + 1) == '@'))
0881 p += 2;
0882 return !*f && !*p;
0883 recursive:
0884
0885
0886
0887
0888
0889
0890 if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
0891 *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
0892 return false;
0893 do {
0894
0895 if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
0896 p_delimiter - 2))
0897 break;
0898
0899 f = f_delimiter;
0900 if (!*f)
0901 break;
0902 f++;
0903
0904 if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
0905 return true;
0906 f_delimiter = strchr(f, '/');
0907 } while (f_delimiter);
0908 return false;
0909 }
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937 bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
0938 const struct tomoyo_path_info *pattern)
0939 {
0940 const char *f = filename->name;
0941 const char *p = pattern->name;
0942 const int len = pattern->const_len;
0943
0944
0945 if (!pattern->is_patterned)
0946 return !tomoyo_pathcmp(filename, pattern);
0947
0948 if (filename->is_dir != pattern->is_dir)
0949 return false;
0950
0951 if (strncmp(f, p, len))
0952 return false;
0953 f += len;
0954 p += len;
0955 return tomoyo_path_matches_pattern2(f, p);
0956 }
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966 const char *tomoyo_get_exe(void)
0967 {
0968 struct file *exe_file;
0969 const char *cp;
0970 struct mm_struct *mm = current->mm;
0971
0972 if (!mm)
0973 return NULL;
0974 exe_file = get_mm_exe_file(mm);
0975 if (!exe_file)
0976 return NULL;
0977
0978 cp = tomoyo_realpath_from_path(&exe_file->f_path);
0979 fput(exe_file);
0980 return cp;
0981 }
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992 int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
0993 const u8 index)
0994 {
0995 u8 mode;
0996 struct tomoyo_profile *p;
0997
0998 if (!tomoyo_policy_loaded)
0999 return TOMOYO_CONFIG_DISABLED;
1000 p = tomoyo_profile(ns, profile);
1001 mode = p->config[index];
1002 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
1003 mode = p->config[tomoyo_index2category[index]
1004 + TOMOYO_MAX_MAC_INDEX];
1005 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
1006 mode = p->default_config;
1007 return mode & 3;
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 int tomoyo_init_request_info(struct tomoyo_request_info *r,
1020 struct tomoyo_domain_info *domain, const u8 index)
1021 {
1022 u8 profile;
1023
1024 memset(r, 0, sizeof(*r));
1025 if (!domain)
1026 domain = tomoyo_domain();
1027 r->domain = domain;
1028 profile = domain->profile;
1029 r->profile = profile;
1030 r->type = index;
1031 r->mode = tomoyo_get_mode(domain->ns, profile, index);
1032 return r->mode;
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
1045 {
1046 unsigned int count = 0;
1047 struct tomoyo_domain_info *domain = r->domain;
1048 struct tomoyo_acl_info *ptr;
1049
1050 if (r->mode != TOMOYO_CONFIG_LEARNING)
1051 return false;
1052 if (!domain)
1053 return true;
1054 if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED]))
1055 return false;
1056 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
1057 srcu_read_lock_held(&tomoyo_ss)) {
1058 u16 perm;
1059
1060 if (ptr->is_deleted)
1061 continue;
1062
1063
1064
1065
1066
1067 switch (ptr->type) {
1068 case TOMOYO_TYPE_PATH_ACL:
1069 perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm);
1070 break;
1071 case TOMOYO_TYPE_PATH2_ACL:
1072 perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm);
1073 break;
1074 case TOMOYO_TYPE_PATH_NUMBER_ACL:
1075 perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head)
1076 ->perm);
1077 break;
1078 case TOMOYO_TYPE_MKDEV_ACL:
1079 perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
1080 break;
1081 case TOMOYO_TYPE_INET_ACL:
1082 perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm);
1083 break;
1084 case TOMOYO_TYPE_UNIX_ACL:
1085 perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm);
1086 break;
1087 case TOMOYO_TYPE_MANUAL_TASK_ACL:
1088 perm = 0;
1089 break;
1090 default:
1091 perm = 1;
1092 }
1093 count += hweight16(perm);
1094 }
1095 if (count < tomoyo_profile(domain->ns, domain->profile)->
1096 pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
1097 return true;
1098 WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true);
1099
1100 tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
1101 #ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
1102 pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
1103 domain->domainname->name);
1104 #endif
1105 return false;
1106 }