|
38 | 38 | #include "runopts.h" |
39 | 39 | #include "auth.h" |
40 | 40 |
|
| 41 | +#ifdef DROPBEAR_ENABLE_SELINUX |
| 42 | +# include <selinux/selinux.h> |
| 43 | +#endif |
| 44 | + |
41 | 45 | /* Handles sessions (either shells or programs) requested by the client */ |
42 | 46 |
|
43 | 47 | static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, |
@@ -573,6 +577,53 @@ static void get_termmodes(const struct ChanSess *chansess) { |
573 | 577 | TRACE(("leave get_termmodes")) |
574 | 578 | } |
575 | 579 |
|
| 580 | +static void relabelpty(const char *tty) |
| 581 | +{ |
| 582 | +#ifdef DROPBEAR_ENABLE_SELINUX |
| 583 | + char *old_sid = NULL; |
| 584 | + char *new_sid = NULL; |
| 585 | + security_class_t class; |
| 586 | + int rc; |
| 587 | + |
| 588 | + if (!is_selinux_enabled()) |
| 589 | + return; |
| 590 | + |
| 591 | + rc = getfilecon(tty, &old_sid); |
| 592 | + if (rc < 0) { |
| 593 | + dropbear_log(LOG_ERR, "failed to get context of tty '%s'", tty); |
| 594 | + goto out; |
| 595 | + } |
| 596 | + |
| 597 | + class = string_to_security_class("chr_file"); |
| 598 | + if (!class) { |
| 599 | + rc = -1; |
| 600 | + dropbear_log(LOG_ERR, "SELinux: failed to map 'chr_file'"); |
| 601 | + goto out; |
| 602 | + } |
| 603 | + |
| 604 | + rc = security_compute_relabel(ses.authstate.user_sid, old_sid, class, &new_sid); |
| 605 | + if (rc < 0) { |
| 606 | + dropbear_log(LOG_ERR, "failed to compute tty relabel"); |
| 607 | + goto out; |
| 608 | + } |
| 609 | + |
| 610 | + rc = setfilecon(tty, new_sid); |
| 611 | + if (rc < 0) { |
| 612 | + dropbear_log(LOG_ERR, "failed to set file context for '%s'", tty); |
| 613 | + goto out; |
| 614 | + } |
| 615 | + |
| 616 | + rc = 0; |
| 617 | + |
| 618 | +out: |
| 619 | + freecon(new_sid); |
| 620 | + freecon(old_sid); |
| 621 | + |
| 622 | + if (rc < 0 && security_getenforce() > 0) |
| 623 | + dropbear_exit("SELinux: failed to relabel PTY"); |
| 624 | +#endif |
| 625 | +} |
| 626 | + |
576 | 627 | /* Set up a session pty which will be used to execute the shell or program. |
577 | 628 | * The pty is allocated now, and kept for when the shell/program executes. |
578 | 629 | * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
@@ -621,6 +672,8 @@ static int sessionpty(struct ChanSess * chansess) { |
621 | 672 | /* Read the terminal modes */ |
622 | 673 | get_termmodes(chansess); |
623 | 674 |
|
| 675 | + relabelpty(chansess->tty); |
| 676 | + |
624 | 677 | TRACE(("leave sessionpty")) |
625 | 678 | return DROPBEAR_SUCCESS; |
626 | 679 | } |
@@ -743,6 +796,29 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, |
743 | 796 | return ret; |
744 | 797 | } |
745 | 798 |
|
| 799 | +static void init_selinux_session(void) |
| 800 | +{ |
| 801 | +#ifdef DROPBEAR_ENABLE_SELINUX |
| 802 | + char *ctx = ses.authstate.user_sid; |
| 803 | + int rc; |
| 804 | + |
| 805 | + if (!is_selinux_enabled()) |
| 806 | + return; |
| 807 | + |
| 808 | + rc = setexeccon(ctx); |
| 809 | + if (rc < 0) { |
| 810 | + dropbear_log(LOG_ERR, "setexeccon() failed"); |
| 811 | + goto out; |
| 812 | + } |
| 813 | + |
| 814 | + rc = 0; |
| 815 | + |
| 816 | +out: |
| 817 | + if (rc < 0 && security_getenforce() > 0) |
| 818 | + dropbear_exit("SELinux: failed to initialize session"); |
| 819 | +#endif |
| 820 | +} |
| 821 | + |
746 | 822 | /* Execute a command and set up redirection of stdin/stdout/stderr without a |
747 | 823 | * pty. |
748 | 824 | * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
@@ -949,6 +1025,8 @@ static void execchild(const void *user_data) { |
949 | 1025 | #endif /* HAVE_CLEARENV */ |
950 | 1026 | #endif /* DEBUG_VALGRIND */ |
951 | 1027 |
|
| 1028 | + init_selinux_session(); |
| 1029 | + |
952 | 1030 | /* We can only change uid/gid as root ... */ |
953 | 1031 | if (getuid() == 0) { |
954 | 1032 |
|
|
0 commit comments