diff options
author | netblue30 <netblue30@yahoo.com> | 2017-07-31 07:09:41 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-31 07:09:41 -0400 |
commit | afe4b1dada830895aac46f1a51d235ce893b9571 (patch) | |
tree | 81534aee83bfd0c5cfc1b09410e48842540bde1b /src | |
parent | Fixes for the private-lib and memory-deny-write-execute features (diff) | |
parent | Ensure malloc was successful (diff) | |
download | firejail-afe4b1dada830895aac46f1a51d235ce893b9571.tar.gz firejail-afe4b1dada830895aac46f1a51d235ce893b9571.tar.zst firejail-afe4b1dada830895aac46f1a51d235ce893b9571.zip |
Merge pull request #1415 from chiraag-nataraj/master
Tentative implementation for #1405
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/x11.c | 320 |
1 files changed, 175 insertions, 145 deletions
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index c6bb7e1e3..7b21c2209 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -665,10 +665,43 @@ void x11_start_xpra(int argc, char **argv) { | |||
665 | 665 | ||
666 | // build the start command | 666 | // build the start command |
667 | char *server_argv[256] = { // rest initialyzed to NULL | 667 | char *server_argv[256] = { // rest initialyzed to NULL |
668 | "xpra", "start", display_str, "--no-daemon", | 668 | "xpra", "start", display_str, "--daemon=no", "--attach=yes", "--exit-with-children=yes" |
669 | }; | 669 | }; |
670 | unsigned pos = 0; | 670 | unsigned spos = 0; |
671 | while (server_argv[pos] != NULL) pos++; | 671 | unsigned fpos = 0; |
672 | while (server_argv[spos] != NULL) spos++; | ||
673 | |||
674 | // build jail command | ||
675 | char *firejail_argv[argc+2]; | ||
676 | size_t total_length = 0; | ||
677 | for (i = 0; i < argc; i++) { | ||
678 | if (strncmp(argv[i], "--x11", 5) == 0) | ||
679 | continue; | ||
680 | firejail_argv[fpos] = argv[i]; | ||
681 | fpos++; | ||
682 | total_length += strlen(argv[i]); | ||
683 | } | ||
684 | |||
685 | char *start_child_prefix = "--start-child="; | ||
686 | char *start_child; | ||
687 | start_child = malloc(total_length + strlen(start_child_prefix) + fpos + 2); | ||
688 | if (start_child == NULL) | ||
689 | { | ||
690 | fprintf(stderr, "Error: unable to allocate start_child to assemble command\n"); | ||
691 | exit(1); | ||
692 | } | ||
693 | |||
694 | strcpy(start_child,start_child_prefix); | ||
695 | for(i = 0; i < fpos; i++) { | ||
696 | strncat(start_child,firejail_argv[i],strlen(firejail_argv[i])); | ||
697 | if(i != fpos - 1) | ||
698 | strncat(start_child," ",strlen(" ")); | ||
699 | } | ||
700 | |||
701 | server_argv[spos++] = start_child; | ||
702 | |||
703 | server_argv[spos++] = NULL; | ||
704 | firejail_argv[fpos] = NULL; | ||
672 | 705 | ||
673 | assert(xpra_extra_params); // should be "" if empty | 706 | assert(xpra_extra_params); // should be "" if empty |
674 | 707 | ||
@@ -702,26 +735,28 @@ void x11_start_xpra(int argc, char **argv) { | |||
702 | exit(1); | 735 | exit(1); |
703 | } | 736 | } |
704 | 737 | ||
705 | server_argv[pos++] = temp; | 738 | server_argv[spos++] = temp; |
706 | for (i = 0; i < (int) strlen(xpra_extra_params)-1; i++) { | 739 | for (i = 0; i < (int) strlen(xpra_extra_params)-1; i++) { |
707 | if (pos >= (sizeof(server_argv)/sizeof(*server_argv)) - 2) { | 740 | if (spos >= (sizeof(server_argv)/sizeof(*server_argv)) - 2) { |
708 | fprintf(stderr, "Error: arg count limit exceeded while parsing xpra_extra_params\n"); | 741 | fprintf(stderr, "Error: arg count limit exceeded while parsing xpra_extra_params\n"); |
709 | exit(1); | 742 | exit(1); |
710 | } | 743 | } |
711 | if (temp[i] == '\0' && (temp[i+1] == '\"' || temp[i+1] == '\'')) { | 744 | if (temp[i] == '\0' && (temp[i+1] == '\"' || temp[i+1] == '\'')) { |
712 | server_argv[pos++] = temp + i + 2; | 745 | server_argv[spos++] = temp + i + 2; |
713 | } | 746 | } |
714 | else if (temp[i] == '\0' && temp[i+1] != '\0') { | 747 | else if (temp[i] == '\0' && temp[i+1] != '\0') { |
715 | server_argv[pos++] = temp + i + 1; | 748 | server_argv[spos++] = temp + i + 1; |
716 | } | 749 | } |
717 | } | 750 | } |
718 | } | 751 | } |
719 | 752 | ||
720 | server_argv[pos++] = NULL; | 753 | assert((int) fpos < (argc+2)); |
721 | 754 | assert(!firejail_argv[fpos]); | |
722 | // no overrun | 755 | // no overrun |
723 | assert(pos < (sizeof(server_argv)/sizeof(*server_argv))); | 756 | assert(spos < (sizeof(server_argv)/sizeof(*server_argv))); |
724 | assert(server_argv[pos-1] == NULL); // last element is null | 757 | assert(server_argv[spos-1] == NULL); // last element is null |
758 | |||
759 | |||
725 | 760 | ||
726 | if (arg_debug) { | 761 | if (arg_debug) { |
727 | size_t i = 0; | 762 | size_t i = 0; |
@@ -761,142 +796,137 @@ void x11_start_xpra(int argc, char **argv) { | |||
761 | _exit(1); | 796 | _exit(1); |
762 | } | 797 | } |
763 | 798 | ||
764 | // add a small delay, on some systems it takes some time for the server to start | 799 | /* // add a small delay, on some systems it takes some time for the server to start */ |
765 | sleep(5); | 800 | /* sleep(5); */ |
766 | 801 | ||
767 | // check X11 socket | 802 | /* // check X11 socket */ |
768 | char *fname; | 803 | /* char *fname; */ |
769 | if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) | 804 | /* if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) */ |
770 | errExit("asprintf"); | 805 | /* errExit("asprintf"); */ |
771 | int n = 0; | 806 | /* int n = 0; */ |
772 | // wait for x11 server to start | 807 | /* // wait for x11 server to start */ |
773 | while (++n < 10) { | 808 | /* while (++n < 10) { */ |
774 | sleep(1); | 809 | /* sleep(1); */ |
775 | if (stat(fname, &s) == 0) | 810 | /* if (stat(fname, &s) == 0) */ |
776 | break; | 811 | /* break; */ |
777 | } | 812 | /* } */ |
778 | 813 | ||
779 | if (n == 10) { | 814 | /* if (n == 10) { */ |
780 | fprintf(stderr, "Error: failed to start xpra\n"); | 815 | /* fprintf(stderr, "Error: failed to start xpra\n"); */ |
781 | exit(1); | 816 | /* exit(1); */ |
782 | } | 817 | /* } */ |
783 | free(fname); | 818 | /* free(fname); */ |
784 | 819 | ||
785 | if (arg_debug) { | 820 | /* if (arg_debug) { */ |
786 | printf("X11 sockets: "); fflush(0); | 821 | /* printf("X11 sockets: "); fflush(0); */ |
787 | int rv = system("ls /tmp/.X11-unix"); | 822 | /* int rv = system("ls /tmp/.X11-unix"); */ |
788 | (void) rv; | 823 | /* (void) rv; */ |
789 | } | 824 | /* } */ |
790 | 825 | ||
791 | // build attach command | 826 | /* // build attach command */ |
792 | char *attach_argv[] = { "xpra", "--title=\"firejail x11 sandbox\"", "attach", display_str, NULL }; | 827 | /* char *attach_argv[] = { "xpra", "--title=\"firejail x11 sandbox\"", "attach", display_str, NULL }; */ |
793 | 828 | ||
794 | // run attach command | 829 | /* // run attach command */ |
795 | client = fork(); | 830 | /* client = fork(); */ |
796 | if (client < 0) | 831 | /* if (client < 0) */ |
797 | errExit("fork"); | 832 | /* errExit("fork"); */ |
798 | if (client == 0) { | 833 | /* if (client == 0) { */ |
799 | if (arg_quiet && fd_null != -1) { | 834 | /* if (arg_quiet && fd_null != -1) { */ |
800 | dup2(fd_null,0); | 835 | /* dup2(fd_null,0); */ |
801 | dup2(fd_null,1); | 836 | /* dup2(fd_null,1); */ |
802 | dup2(fd_null,2); | 837 | /* dup2(fd_null,2); */ |
803 | } | 838 | /* } */ |
804 | 839 | ||
805 | if (!arg_quiet) | 840 | /* if (!arg_quiet) */ |
806 | printf("\n*** Attaching to xpra display %d ***\n\n", display); | 841 | /* printf("\n*** Attaching to xpra display %d ***\n\n", display); */ |
807 | 842 | ||
808 | // running without privileges - see drop_privs call above | 843 | /* // running without privileges - see drop_privs call above */ |
809 | assert(getenv("LD_PRELOAD") == NULL); | 844 | /* assert(getenv("LD_PRELOAD") == NULL); */ |
810 | execvp(attach_argv[0], attach_argv); | 845 | /* execvp(attach_argv[0], attach_argv); */ |
811 | perror("execvp"); | 846 | /* perror("execvp"); */ |
812 | _exit(1); | 847 | /* _exit(1); */ |
813 | } | 848 | /* } */ |
814 | 849 | ||
815 | assert(display_str); | 850 | /* assert(display_str); */ |
816 | setenv("DISPLAY", display_str, 1); | 851 | /* setenv("DISPLAY", display_str, 1); */ |
817 | 852 | ||
818 | // build jail command | 853 | /* // start jail */ |
819 | char *firejail_argv[argc+2]; | 854 | /* pid_t jail = fork(); */ |
820 | pos = 0; | 855 | /* if (jail < 0) */ |
821 | for (i = 0; i < argc; i++) { | 856 | /* errExit("fork"); */ |
822 | if (strncmp(argv[i], "--x11", 5) == 0) | 857 | /* if (jail == 0) { */ |
823 | continue; | 858 | /* // running without privileges - see drop_privs call above */ |
824 | firejail_argv[pos] = argv[i]; | 859 | /* assert(getenv("LD_PRELOAD") == NULL); */ |
825 | pos++; | 860 | /* if (firejail_argv[0]) // shut up llvm scan-build */ |
826 | } | 861 | /* execvp(firejail_argv[0], firejail_argv); */ |
827 | firejail_argv[pos] = NULL; | 862 | /* perror("execvp"); */ |
828 | 863 | /* exit(1); */ | |
829 | assert((int) pos < (argc+2)); | 864 | /* } */ |
830 | assert(!firejail_argv[pos]); | 865 | |
831 | 866 | /* if (!arg_quiet) */ | |
832 | // start jail | 867 | /* printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail); */ |
833 | pid_t jail = fork(); | 868 | |
834 | if (jail < 0) | 869 | /* sleep(1); // adding a delay in order to let the server start */ |
835 | errExit("fork"); | 870 | |
836 | if (jail == 0) { | 871 | // wait for server to end |
837 | // running without privileges - see drop_privs call above | ||
838 | assert(getenv("LD_PRELOAD") == NULL); | ||
839 | if (firejail_argv[0]) // shut up llvm scan-build | ||
840 | execvp(firejail_argv[0], firejail_argv); | ||
841 | perror("execvp"); | ||
842 | exit(1); | ||
843 | } | ||
844 | |||
845 | if (!arg_quiet) | ||
846 | printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail); | ||
847 | |||
848 | sleep(1); // adding a delay in order to let the server start | ||
849 | |||
850 | // wait for jail or server to end | ||
851 | while (1) { | 872 | while (1) { |
852 | pid_t pid = wait(NULL); | 873 | pid_t pid = wait(NULL); |
853 | 874 | if (pid == server) { | |
854 | if (pid == jail) { | 875 | free(start_child); |
855 | char *stop_argv[] = { "xpra", "stop", display_str, NULL }; | 876 | exit(0); |
856 | pid_t stop = fork(); | 877 | } |
857 | if (stop < 0) | ||
858 | errExit("fork"); | ||
859 | if (stop == 0) { | ||
860 | if (arg_quiet && fd_null != -1) { | ||
861 | dup2(fd_null,0); | ||
862 | dup2(fd_null,1); | ||
863 | dup2(fd_null,2); | ||
864 | } | ||
865 | // running without privileges - see drop_privs call above | ||
866 | assert(getenv("LD_PRELOAD") == NULL); | ||
867 | execvp(stop_argv[0], stop_argv); | ||
868 | perror("execvp"); | ||
869 | _exit(1); | ||
870 | } | ||
871 | |||
872 | // wait for xpra server to stop, 10 seconds limit | ||
873 | while (++n < 10) { | ||
874 | sleep(1); | ||
875 | pid = waitpid(server, NULL, WNOHANG); | ||
876 | if (pid == server) | ||
877 | break; | ||
878 | } | ||
879 | |||
880 | if (arg_debug) { | ||
881 | if (n == 10) | ||
882 | printf("failed to stop xpra server gratefully\n"); | ||
883 | else | ||
884 | printf("xpra server successfully stopped in %d secs\n", n); | ||
885 | } | ||
886 | |||
887 | // kill xpra server and xpra client | ||
888 | kill(client, SIGTERM); | ||
889 | kill(server, SIGTERM); | ||
890 | exit(0); | ||
891 | } | ||
892 | else if (pid == server) { | ||
893 | // kill firejail process | ||
894 | kill(jail, SIGTERM); | ||
895 | // kill xpra client (should die with server, but...) | ||
896 | kill(client, SIGTERM); | ||
897 | exit(0); | ||
898 | } | ||
899 | } | 878 | } |
879 | |||
880 | // wait for jail or server to end | ||
881 | /* while (1) { */ | ||
882 | /* pid_t pid = wait(NULL); */ | ||
883 | |||
884 | /* if (pid == jail) { */ | ||
885 | /* char *stop_argv[] = { "xpra", "stop", display_str, NULL }; */ | ||
886 | /* pid_t stop = fork(); */ | ||
887 | /* if (stop < 0) */ | ||
888 | /* errExit("fork"); */ | ||
889 | /* if (stop == 0) { */ | ||
890 | /* if (arg_quiet && fd_null != -1) { */ | ||
891 | /* dup2(fd_null,0); */ | ||
892 | /* dup2(fd_null,1); */ | ||
893 | /* dup2(fd_null,2); */ | ||
894 | /* } */ | ||
895 | /* // running without privileges - see drop_privs call above */ | ||
896 | /* assert(getenv("LD_PRELOAD") == NULL); */ | ||
897 | /* execvp(stop_argv[0], stop_argv); */ | ||
898 | /* perror("execvp"); */ | ||
899 | /* _exit(1); */ | ||
900 | /* } */ | ||
901 | |||
902 | /* // wait for xpra server to stop, 10 seconds limit */ | ||
903 | /* while (++n < 10) { */ | ||
904 | /* sleep(1); */ | ||
905 | /* pid = waitpid(server, NULL, WNOHANG); */ | ||
906 | /* if (pid == server) */ | ||
907 | /* break; */ | ||
908 | /* } */ | ||
909 | |||
910 | /* if (arg_debug) { */ | ||
911 | /* if (n == 10) */ | ||
912 | /* printf("failed to stop xpra server gratefully\n"); */ | ||
913 | /* else */ | ||
914 | /* printf("xpra server successfully stopped in %d secs\n", n); */ | ||
915 | /* } */ | ||
916 | |||
917 | /* // kill xpra server and xpra client */ | ||
918 | /* kill(client, SIGTERM); */ | ||
919 | /* kill(server, SIGTERM); */ | ||
920 | /* exit(0); */ | ||
921 | /* } */ | ||
922 | /* else if (pid == server) { */ | ||
923 | /* // kill firejail process */ | ||
924 | /* kill(jail, SIGTERM); */ | ||
925 | /* // kill xpra client (should die with server, but...) */ | ||
926 | /* kill(client, SIGTERM); */ | ||
927 | /* exit(0); */ | ||
928 | /* } */ | ||
929 | /* } */ | ||
900 | } | 930 | } |
901 | 931 | ||
902 | 932 | ||