(/home/sate/Testcases/c/cve/dovecot-1.2.0/src/master/mail-process.c) |
| |
| 551 | | | create_mail_process(enum process_type process_type, struct settings *set, |
| 552 | | | const struct mail_login_request *request, |
| 553 | | | const char *user, const char *const *args, |
| 554 | | | const unsigned char *data, bool dump_capability, |
| 555 | | | pid_t *pid_r) |
| 556 | | | { |
| 557 | | | const struct var_expand_table *var_expand_table; |
| 558 | | | const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir; |
| 559 | | | const char *system_groups_user, *master_user; |
| 560 | | | struct mail_process_group *process_group; |
| 561 | | | char title[1024]; |
| 562 | | | struct log_io *log; |
| 563 | | | string_t *str; |
| 564 | | | pid_t pid; |
| 565 | | | uid_t uid; |
| 566 | | | gid_t gid; |
| 567 | | | ARRAY_DEFINE(, const char *);
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array-decl.h |
| |
4 | #define ARRAY_DEFINE(name, array_type) union { struct array arr; array_type const *const *v; array_type **v_modifiable; } name |
| |
|
| 568 | | | unsigned int i, len, count, left, process_count, throttle; |
| 569 | | | int ret, log_fd, nice_value, chdir_errno; |
| 570 | | | bool home_given, nfs_check; |
| 571 | | | |
| 572 | | | i_assert(process_type == PROCESS_TYPE_IMAP ||
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/macros.h |
| |
189 | #define i_assert(expr) STMT_START{ \ |
190 | if (unlikely(!(expr))) \ |
191 | i_panic("file %s: line %d (%s): assertion failed: (%s)", \ |
192 | __FILE__, \ |
193 | __LINE__, \ |
194 | __PRETTY_FUNCTION__, \ |
195 | #expr); }STMT_END |
| |
|
| 573 | | | process_type == PROCESS_TYPE_POP3); |
Event 1:
Skipping " if". process_type == PROCESS_TYPE_IMAP evaluates to true.
hide
Event 2:
Skipping " if". !(process_type == PROCESS_TYPE_IMAP || process_type == PROCESS_TYPE_POP3) evaluates to false.
hide
Event 3:
Skipping " if". !!(process_type == PROCESS_TYPE_IMAP || process_type == PROCESS_TYPE_POP3) evaluates to true.
hide
Event 4:
Skipping " if". !!!(process_type == PROCESS_TYPE_IMAP || process_type == PROCESS_TYPE_POP3) evaluates to false.
hide
Event 5:
Skipping " if". __builtin_expect(...) evaluates to false.
hide
|
|
| 574 | | | |
| 575 | | | if (mail_process_count == set->max_mail_processes) { |
Event 6:
Skipping " if". mail_process_count == set->max_mail_processes evaluates to false.
hide
|
|
| 576 | | | i_error("Maximum number of mail processes exceeded " |
| 577 | | | "(see max_mail_processes setting)"); |
| 578 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 579 | | | } |
| 580 | | | |
| 581 | | | t_array_init(&, 16);
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
39 | #define t_array_init(array, init_count) \ |
40 | p_array_init(array, pool_datastack_create(), init_count) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
35 | #define p_array_init(array, pool, init_count) \ |
36 | array_create(array, pool, sizeof(**(array)->v), init_count) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
75 | #define array_create(array, pool, element_size, init_count) \ |
76 | array_create_i(&(array)->arr, pool, element_size, init_count) |
| |
|
| 582 | | | mail = home_dir = chroot_dir = system_groups_user = ""; |
| 583 | | | master_user = NULL; |
| 584 | | | uid = (uid_t)-1; gid = (gid_t)-1; nice_value = 0; |
| 585 | | | home_given = FALSE; |
| 586 | | | for (; *args != NULL; args++) { |
| 587 | | | if (strncmp(*args, "home=", 5) == 0) { |
| 588 | | | home_dir = *args + 5; |
| 589 | | | home_given = TRUE; |
| 590 | | | } else if (strncmp(*args, "mail=", 5) == 0) |
| 591 | | | mail = *args + 5; |
| 592 | | | else if (strncmp(*args, "chroot=", 7) == 0) |
| 593 | | | chroot_dir = *args + 7; |
| 594 | | | else if (strncmp(*args, "nice=", 5) == 0) |
| 595 | | | nice_value = atoi(*args + 5); |
| 596 | | | else if (strncmp(*args, "system_groups_user=", 19) == 0) |
| 597 | | | system_groups_user = *args + 19; |
| 598 | | | else if (strncmp(*args, "uid=", 4) == 0) { |
| 599 | | | if (uid != (uid_t)-1) { |
| 600 | | | i_error("uid specified multiple times for %s", |
| 601 | | | user); |
| 602 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 603 | | | } |
| 604 | | | uid = (uid_t)strtoul(*args + 4, NULL, 10); |
| 605 | | | } else if (strncmp(*args, "gid=", 4) == 0) { |
| 606 | | | gid = (gid_t)strtoul(*args + 4, NULL, 10); |
| 607 | | | } else if (strncmp(*args, "master_user=", 12) == 0) { |
| 608 | | | const char *arg = *args; |
| 609 | | | |
| 610 | | | master_user = arg + 12; |
| 611 | | | array_append(&, &arg, 1);
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
116 | #define array_append(array, data, count) \ |
117 | array_append_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \ |
118 | data, count) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
47 | # define ARRAY_TYPE_CHECK(array, data) \ |
48 | COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \ |
49 | **(array)->v_modifiable, *data) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/macros.h |
| |
158 | # define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) \ |
159 | COMPILE_ERROR_IF_TRUE( \ |
160 | !__builtin_types_compatible_p(typeof(_a), typeof(_b))) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/macros.h |
| |
156 | # define COMPILE_ERROR_IF_TRUE(condition) \ |
157 | (sizeof(char[1 - 2 * !!(condition)]) - 1) |
| |
|
| 612 | | | } else { |
| 613 | | | const char *arg = *args; |
| 614 | | | array_append(&, &arg, 1);
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
116 | #define array_append(array, data, count) \ |
117 | array_append_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \ |
118 | data, count) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/array.h |
| |
47 | # define ARRAY_TYPE_CHECK(array, data) \ |
48 | COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \ |
49 | **(array)->v_modifiable, *data) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/macros.h |
| |
158 | # define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) \ |
159 | COMPILE_ERROR_IF_TRUE( \ |
160 | !__builtin_types_compatible_p(typeof(_a), typeof(_b))) |
| |
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/macros.h |
| |
156 | # define COMPILE_ERROR_IF_TRUE(condition) \ |
157 | (sizeof(char[1 - 2 * !!(condition)]) - 1) |
| |
|
| 615 | | | } |
| 616 | | | } |
| 617 | | | |
| 618 | | | |
| 619 | | | |
| 620 | | | process_group = dump_capability ? NULL : |
Event 8:
dump_capability evaluates to false.
hide
|
|
| 621 | | | mail_process_group_lookup(process_type, user, |
| 622 | | | &request->remote_ip); |
| 623 | | | process_count = process_group == NULL ? 0 : |
Event 9:
process_group == (void *)0 evaluates to true.
hide
|
|
| 624 | | | array_count(&process_group->processes); |
| 625 | | | if (process_count >= set->mail_max_userip_connections && |
Event 10:
Skipping " if". process_count >= set->mail_max_userip_connections evaluates to false.
hide
|
|
| 626 | | | set->mail_max_userip_connections != 0 && |
| 627 | | | master_user == NULL) |
| 628 | | | return MASTER_LOGIN_STATUS_MAX_CONNECTIONS; |
| 629 | | | |
| 630 | | | |
| 631 | | | if (uid == (uid_t)-1) { |
Event 11:
Skipping " if". uid == (uid_t)-1 evaluates to false.
hide
|
|
| 632 | | | uid = set->mail_uid_t; |
| 633 | | | if (uid == (uid_t)-1) { |
| 634 | | | i_error("User %s is missing UID (see mail_uid setting)", |
| 635 | | | user); |
| 636 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 637 | | | } |
| 638 | | | } |
| 639 | | | if (gid == (gid_t)-1) { |
Event 12:
Taking true branch. gid == (gid_t)-1 evaluates to true.
hide
|
|
| 640 | | | gid = set->mail_gid_t; |
| 641 | | | if (gid == (gid_t)-1) { |
Event 13:
Skipping " if". gid == (gid_t)-1 evaluates to false.
hide
|
|
| 642 | | | i_error("User %s is missing GID (see mail_gid setting)", |
| 643 | | | user); |
| 644 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 645 | | | } |
| 646 | | | } |
| 647 | | | |
| 648 | | | if (*chroot_dir == '\0' && *set->valid_chroot_dirs != '\0' && |
| 649 | | | (p = strstr(home_dir, "/./")) != NULL) { |
| 650 | | | |
| 651 | | | |
| 652 | | | chroot_dir = t_strdup_until(home_dir, p); |
| 653 | | | home_dir = p + 2; |
| 654 | | | } else if (*chroot_dir != '\0' && *home_dir != '/') { |
Event 15:
Skipping " if". *chroot_dir != 0 evaluates to false.
hide
|
|
| 655 | | | |
| 656 | | | |
| 657 | | | home_dir = t_strconcat("/", home_dir, NULL); |
| 658 | | | } |
| 659 | | | |
| 660 | | | if (!dump_capability) { |
Event 16:
Taking true branch. dump_capability evaluates to false.
hide
|
|
| 661 | [+] | | if (!validate_uid_gid(set, uid, gid, user)) |
 |
| 662 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 663 | | | } |
| 664 | | | |
| 665 | | | if (*chroot_dir != '\0') { |
Event 23:
Taking false branch. *chroot_dir != 0 evaluates to false.
hide
|
|
| 666 | | | if (!validate_chroot(set, chroot_dir)) { |
| 667 | | | i_error("Invalid chroot directory '%s' (user %s) " |
| 668 | | | "(see valid_chroot_dirs setting)", |
| 669 | | | chroot_dir, user); |
| 670 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 671 | | | } |
| 672 | | | } else if (*set->mail_chroot != '\0') { |
Event 24:
Taking true branch. *set->mail_chroot != 0 evaluates to true.
hide
|
|
| 673 | | | |
| 674 | | | |
| 675 | | | chroot_dir = set->mail_chroot; |
| 676 | | | } |
| 677 | | | if (*chroot_dir != '\0' && set->mail_drop_priv_before_exec) { |
Event 25:
Skipping " if". - *chroot_dir != 0 evaluates to true.
- set->mail_drop_priv_before_exec evaluates to false.
hide
|
|
| 678 | | | i_error("Can't chroot to directory '%s' (user %s) " |
| 679 | | | "with mail_drop_priv_before_exec=yes", |
| 680 | | | chroot_dir, user); |
| 681 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 682 | | | } |
| 683 | | | len = strlen(chroot_dir); |
| 684 | | | if (len > 2 && strcmp(chroot_dir + len - 2, "/.") == 0 && |
Event 26:
Skipping " if". - len > 2 evaluates to true.
- strcmp(...) == 0 evaluates to false.
hide
|
|
| 685 | | | strncmp(home_dir, chroot_dir, len - 2) == 0) { |
| 686 | | | |
| 687 | | | home_dir += len - 2; |
| 688 | | | } |
| 689 | | | |
| 690 | | | if (!dump_capability) { |
Event 27:
Taking true branch. dump_capability evaluates to false.
hide
|
|
| 691 | | | throttle = set->mail_debug ? 0 : |
Event 28:
set->mail_debug evaluates to true.
hide
|
|
| 692 | | | set->mail_log_max_lines_per_sec; |
| 693 | [+] | | log_fd = log_create_pipe(&log, throttle); |
 |
| 694 | | | if (log_fd == -1) |
Event 37:
Skipping " if". log_fd == -1 evaluates to false.
hide
|
|
| 695 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 696 | | | } else { |
| 697 | | | log = NULL; |
| 698 | | | log_fd = dup(STDERR_FILENO);
x /usr/include/unistd.h |
| |
213 | #define STDERR_FILENO 2 /* Standard error output. */ |
| |
|
| 699 | | | if (log_fd == -1) { |
| 700 | | | i_error("dup() failed: %m"); |
| 701 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 702 | | | } |
| 703 | | | fd_close_on_exec(log_fd, TRUE); |
| 704 | | | } |
| 705 | | | |
| 706 | | | |
| 707 | | | |
| 708 | | | if (set->nfs_check && !set->mail_nfs_index && !dump_capability) { |
| 709 | | | set->nfs_check = FALSE; |
| 710 | | | nfs_check = TRUE; |
| 711 | | | } else { |
| 712 | | | nfs_check = FALSE; |
| 713 | | | } |
| 714 | | | |
| 715 | | | pid = fork(); |
| 716 | | | if (pid < 0) { |
Event 39:
Skipping " if". pid < 0 evaluates to false.
hide
|
|
| 717 | | | i_error("fork() failed: %m"); |
| 718 | | | (void)close(log_fd); |
| 719 | | | return MASTER_LOGIN_STATUS_INTERNAL_ERROR; |
| 720 | | | } |
| 721 | | | |
| 722 | | | var_expand_table = |
| 723 | | | get_var_expand_table(process_names[process_type], |
| 724 | | | user, home_given ? home_dir : NULL, |
Event 41:
home_given evaluates to true.
hide
|
|
| 725 | | | net_ip2addr(&request->local_ip), |
| 726 | | | net_ip2addr(&request->remote_ip), |
| 727 | | | pid != 0 ? pid : getpid(), uid); |
Event 40:
pid != 0 evaluates to false.
hide
|
|
| 728 | | | str = t_str_new(128); |
| 729 | | | |
| 730 | | | if (pid != 0) { |
Event 42:
Skipping " if". pid != 0 evaluates to false.
hide
|
|
| 731 | | | |
| 732 | | | var_expand(str, set->mail_log_prefix, var_expand_table); |
| 733 | | | |
| 734 | | | if (!dump_capability) { |
| 735 | | | log_set_prefix(log, str_c(str)); |
| 736 | | | log_set_pid(log, pid); |
| 737 | | | if (process_group == NULL) { |
| 738 | | | process_group = mail_process_group_create( |
| 739 | | | process_type, user, |
| 740 | | | &request->remote_ip); |
| 741 | | | } |
| 742 | | | mail_process_group_add(process_group, pid); |
| 743 | | | } |
| 744 | | | (void)close(log_fd); |
| 745 | | | *pid_r = pid; |
| 746 | | | return MASTER_LOGIN_STATUS_OK; |
| 747 | | | } |
| 748 | | | |
| 749 | | | #ifdef HAVE_SETPRIORITY |
| 750 | | | if (nice_value != 0) { |
Event 43:
Skipping " if". nice_value != 0 evaluates to false.
hide
|
|
| 751 | | | if (setpriority(PRIO_PROCESS, 0, nice_value) < 0)
x /usr/include/bits/resource.h |
| |
229 | #define PRIO_PROCESS PRIO_PROCESS |
| |
|
| 752 | | | i_error("setpriority(%d) failed: %m", nice_value); |
| 753 | | | } |
| 754 | | | #endif |
| 755 | | | |
| 756 | | | if (!dump_capability) { |
Event 44:
Taking true branch. dump_capability evaluates to false.
hide
|
|
| 757 | | | str_append(str, "master-"); |
| 758 | | | var_expand(str, set->mail_log_prefix, var_expand_table); |
| 759 | | | log_set_prefix(log, str_c(str)); |
| 760 | | | } |
| 761 | | | |
| 762 | | | child_process_init_env(); |
| 763 | | | |
| 764 | | | |
| 765 | | | |
| 766 | | | restrict_access_set_env(system_groups_user, uid, gid, |
| 767 | | | set->mail_priv_gid_t, |
| 768 | | | dump_capability ? "" : chroot_dir, |
Event 45:
dump_capability evaluates to false.
hide
|
|
| 769 | | | set->first_valid_gid, set->last_valid_gid, |
| 770 | | | set->mail_access_groups); |
| 771 | | | |
| 772 | | | restrict_process_size(set->mail_process_size, (unsigned int)-1); |
| 773 | | | |
| 774 | | | if (dump_capability) |
Event 46:
Skipping " if". dump_capability evaluates to false.
hide
|
|
| 775 | | | env_put("DUMP_CAPABILITY=1"); |
| 776 | | | |
| 777 | | | if ((*home_dir == '\0' && *chroot_dir == '\0') || dump_capability) { |
| 778 | | | full_home_dir = ""; |
| 779 | | | ret = -1; |
| 780 | | | } else { |
| 781 | | | full_home_dir = *chroot_dir == '\0' ? home_dir : |
Event 48:
*chroot_dir == 0 evaluates to false.
hide
Event 80:
full_home_dir is set to *chroot_dir == 0 ? home_dir : t_strconcat(...), which evaluates to the value assigned to ret at data-stack.c:335. See related event 79.
hide
|
|
| 782 | [+] | | t_strconcat(chroot_dir, home_dir, NULL); |
 |
| 783 | | | |
| 784 | | | |
| 785 | | | |
| 786 | | | if (uid != master_uid) { |
Event 81:
Taking true branch. uid != master_uid evaluates to true.
hide
|
|
| 787 | | | if (setegid(gid) < 0) |
Event 82:
Skipping " if". setegid(gid) < 0 evaluates to false.
hide
|
|
| 788 | | | i_fatal("setegid(%s) failed: %m", dec2str(gid)); |
| 789 | | | if (seteuid(uid) < 0) |
Event 83:
Skipping " if". seteuid(uid) < 0 evaluates to false.
hide
|
|
| 790 | | | i_fatal("seteuid(%s) failed: %m", dec2str(uid)); |
| 791 | | | } |
| 792 | | | |
| 793 | | | alarm(CHDIR_TIMEOUT); |
| 794 | | | ret = chdir(full_home_dir); |
Event 84:
full_home_dir, which evaluates to the value assigned to ret at data-stack.c:335, is passed to chdir(). See related event 80.
hide
Event 85:
chdir() accesses the file named full_home_dir, where full_home_dir is the value assigned to ret at data-stack.c:335. - The same name is used to access a file later, but it is not safe to assume that it will be the same underlying file.
See related event 84.
hide
|
|
| 795 | | | chdir_errno = errno; |
| 796 | | | if ((left = alarm(0)) < CHDIR_TIMEOUT - CHDIR_WARN_SECS) { |
Event 86:
Taking true branch. (left = alarm(0)) < 30 - 10 evaluates to true.
hide
|
|
| 797 | | | i_warning("chdir(%s) blocked for %u secs", |
| 798 | | | full_home_dir, CHDIR_TIMEOUT - left); |
| 799 | | | } |
| 800 | | | |
| 801 | | | |
| 802 | | | |
| 803 | | | if (uid != master_uid && seteuid(master_uid) < 0) |
Event 87:
Skipping " if". - uid != master_uid evaluates to true.
- seteuid(master_uid) < 0 evaluates to false.
hide
|
|
| 804 | | | i_fatal("seteuid(%s) failed: %m", dec2str(master_uid)); |
| 805 | | | |
| 806 | | | |
| 807 | | | |
| 808 | | | |
| 809 | | | |
| 810 | | | if (ret < 0 && (*chroot_dir != '\0' || |
| 811 | | | !(ENOTFOUND(chdir_errno) ||
x /home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/compat.h |
| |
246 | #define ENOTFOUND(errno) \ |
247 | ((errno) == ENOENT || (errno) == ENOTDIR || (errno) == ELOOP) |
| |
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
x /usr/include/asm-generic/errno-base.h |
| |
23 | #define ENOTDIR 20 /* Not a directory */ |
| |
x /usr/include/asm-generic/errno.h |
| |
11 | #define ELOOP 40 /* Too many symbolic links encountered */ |
| |
|
| 812 | | | chdir_errno == EINTR))) {
x /usr/include/asm-generic/errno-base.h |
| |
7 | #define EINTR 4 /* Interrupted system call */ |
| |
|
| 813 | | | errno = chdir_errno; |
| 814 | | | if (errno != EACCES) {
x /usr/include/asm-generic/errno-base.h |
| |
16 | #define EACCES 13 /* Permission denied */ |
| |
|
Event 89:
Taking false branch. errno != 13 evaluates to false.
hide
|
|
| 815 | | | i_fatal("chdir(%s) failed with uid %s: %m", |
| 816 | | | full_home_dir, dec2str(uid)); |
| 817 | | | } else { |
| 818 | | | i_fatal("%s", eacces_error_get("chdir", |
| 819 | [+] | | full_home_dir)); |
Event 90:
full_home_dir, which evaluates to the value assigned to ret at data-stack.c:335, is passed to eacces_error_get() as the second argument. See related event 80.
hide
|
|
 |
| |