Ejemplo n.º 1
0
static int parse_run_args(int argc, char **argv, struct scl_args *args)
{
    int i, ret;
    /* This initialization is important for the condition below */
    int separator_pos = argc-1;

    /* Find the separator (skip the argv[0] and [1]) */
    for (i = 2; i < argc; i++) {
        if (strcmp(argv[i], "--") == 0) {
            separator_pos = i;
            break;
        }
    }
    if (separator_pos == 2) {
        /* No collections specified */
        return EINPUT;
    } else {
        ret = extract_collections(separator_pos, argv, args);
        if (ret != EOK) {
            return ret;
        }

        if (separator_pos > 2 && separator_pos < argc-1) {
            /* Collections and command separated */
            ret = extract_command(argc, argv, separator_pos+1, args);
            if (ret != EOK) {
                goto fail;
            }
        } else {
            /* One of two situations could have happened:
             * a) the separator is the last argument
             * b) the separator was not found
             * => re-test the last argument again
             */
            if (strcmp(argv[separator_pos], "--") != 0) {
                /* Separator not found - the last arg is command */
                args->command = xstrdup(argv[argc-1]);
            } else {
                /* Separator is the last arg -> command from stdin */
                args->command = xstrdup("-");
            }
        }

        if (strcmp(args->command, "-") == 0) {
            free(args->command);
            args->command = NULL; /* In case the subsequent call fails */
            ret = extract_command_stdin(args);
            if (ret != EOK) {
                goto fail;
            }
        }
    }

    return EOK;

fail:
    scl_args_free(args);
    return ret;
}
Ejemplo n.º 2
0
int contains_command(const char *cmdline, const char *cmd)
{
    size_t start = 0, end = 0;

    extract_command(&start, &end, cmdline, cmd);
    if (start == 0 && end == 0)
        return 0;

    return 1;
}
Ejemplo n.º 3
0
static int
complete (int    argc,
          char **argv)
{
  FlatpakCommand *command;
  FlatpakCompletion *completion;
  const char *command_name = NULL;

  completion = flatpak_completion_new (argv[2], argv[3], argv[4]);
  if (completion == NULL)
    return 1;

  command = extract_command (&completion->argc, completion->argv, &command_name);
  flatpak_completion_debug ("command=%p '%s'", command->fn, command->name);

  if (!command->fn)
    {
      FlatpakCommand *c = commands;
      while (c->name)
        {
          if (c->fn != NULL)
            flatpak_complete_word (completion, "%s ", c->name);
          c++;
        }

      flatpak_complete_options (completion, global_entries);
      flatpak_complete_options (completion, empty_entries);
      flatpak_complete_options (completion, user_entries);
    }
  else if (command->complete)
    {
      if (!command->complete (completion))
        return 1;
    }
  else
    {
      flatpak_complete_options (completion, global_entries);
    }

  return 0;
}
Ejemplo n.º 4
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);
	signal (SIGTERM, signal_handler);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc"))
			exit(1);
		if (join_namespace(pid, "net"))
			exit(1);
		if (join_namespace(pid, "pid"))
			exit(1);
		if (join_namespace(pid, "uts"))
			exit(1);
		if (join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set protocol filter
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			protocol_filter();
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_set();
#endif

		// fix qt 4.8
		if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
			errExit("setenv");
		if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
			errExit("setenv");

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);

			// user namespace resets capabilities
			// set caps filter
			if (apply_caps == 1)	// not available for uid 0
				caps_set(caps);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0


		// set prompt color to green
		char *prompt = getenv("FIREJAIL_PROMPT");
		if (prompt && strcmp(prompt, "yes") == 0) {
			//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
			if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
				errExit("setenv");
		}
		
		// set nice
		if (arg_nice) {
			errno = 0;
			int rv = nice(cfg.nice);
			(void) rv;
			if (errno) {
				fprintf(stderr, "Warning: cannot set nice value\n");
				errno = 0;
			}
		}

		// run cmdline trough shell
		if (cfg.command_line == NULL) {
			// if the sandbox was started with --shell=none, it is possible we don't have a shell
			// inside the sandbox
			if (cfg.shell == NULL) {
				cfg.shell = guess_shell();
				if (!cfg.shell) {
					fprintf(stderr, "Error: no POSIX shell found, please use --shell command line option\n");
					exit(1);
				}
			}
				
			struct stat s;
			if (stat(cfg.shell, &s) == -1)  {
				fprintf(stderr, "Error: %s shell not found inside the sandbox\n", cfg.shell);
				exit(1);
			}

			cfg.command_line = cfg.shell;
			cfg.window_title = cfg.shell;
		}

		int cwd = 0;
		if (cfg.cwd) {
			if (chdir(cfg.cwd) == 0)
				cwd = 1;
		}

		if (!cwd) {
			if (chdir("/") < 0)
				errExit("chdir");
			if (cfg.homedir) {
				struct stat s;
				if (stat(cfg.homedir, &s) == 0) {
					/* coverity[toctou] */
					if (chdir(cfg.homedir) < 0)
						errExit("chdir");
				}
			}
		}

		start_application();

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	flush_stdin();
	exit(0);
}
Ejemplo n.º 5
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc"))
			exit(1);
		if (join_namespace(pid, "net"))
			exit(1);
		if (join_namespace(pid, "pid"))
			exit(1);
		if (join_namespace(pid, "uts"))
			exit(1);
		if (join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set protocol filter
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			protocol_filter();
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_set();
		
#endif
		
		// fix qt 4.8
		if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
			errExit("setenv");
		if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
			errExit("setenv");

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0

		// set prompt color to green
		//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
		if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
			errExit("setenv");

		// run cmdline trough /bin/bash
		if (cfg.command_line == NULL) {
			struct stat s;

			// replace the process with a shell
			if (stat("/bin/bash", &s) == 0)
				execlp("/bin/bash", "/bin/bash", NULL);
			else if (stat("/usr/bin/zsh", &s) == 0)
				execlp("/usr/bin/zsh", "/usr/bin/zsh", NULL);
			else if (stat("/bin/csh", &s) == 0)
				execlp("/bin/csh", "/bin/csh", NULL);
			else if (stat("/bin/sh", &s) == 0)
				execlp("/bin/sh", "/bin/sh", NULL);
			
			// no shell found, print an error and exit
			fprintf(stderr, "Error: no POSIX shell found\n");
			sleep(5);
			exit(1);
		}
		else {
			// run the command supplied by the user
			int cwd = 0;
			if (cfg.cwd) {
				if (chdir(cfg.cwd) == 0)
					cwd = 1;
			}
			
			if (!cwd) {
				if (chdir("/") < 0)
					errExit("chdir");
				if (cfg.homedir) {
					struct stat s;
					if (stat(cfg.homedir, &s) == 0) {
						if (chdir(cfg.homedir) < 0)
							errExit("chdir");
					}
				}
			}

			char *arg[5];
			arg[0] = "/bin/bash";
			arg[1] = "-c";
			if (arg_debug)
				printf("Starting %s\n", cfg.command_line);
			if (!arg_doubledash) {
				arg[2] = cfg.command_line;
				arg[3] = NULL;
			}
			else {
				arg[2] = "--";
				arg[3] = cfg.command_line;
				arg[4] = NULL;
			}
			execvp("/bin/bash", arg);
		}

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	exit(0);
}
Ejemplo n.º 6
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);
	signal (SIGTERM, signal_handler);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc") ||
		    join_namespace(pid, "net") ||
		    join_namespace(pid, "pid") ||
		    join_namespace(pid, "uts") ||
		    join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// read cfg.protocol from file
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			seccomp_load(RUN_SECCOMP_PROTOCOL);	// install filter	
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_load(RUN_SECCOMP_CFG);
#endif

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);

			// user namespace resets capabilities
			// set caps filter
			if (apply_caps == 1)	// not available for uid 0
				caps_set(caps);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0


		// set nice
		if (arg_nice) {
			errno = 0;
			int rv = nice(cfg.nice);
			(void) rv;
			if (errno) {
				fprintf(stderr, "Warning: cannot set nice value\n");
				errno = 0;
			}
		}

		env_defaults();
		if (cfg.command_line == NULL) {
			assert(cfg.shell);
			cfg.command_line = cfg.shell;
			cfg.window_title = cfg.shell;
		}

		int cwd = 0;
		if (cfg.cwd) {
			if (chdir(cfg.cwd) == 0)
				cwd = 1;
		}

		if (!cwd) {
			if (chdir("/") < 0)
				errExit("chdir");
			if (cfg.homedir) {
				struct stat s;
				if (stat(cfg.homedir, &s) == 0) {
					/* coverity[toctou] */
					if (chdir(cfg.homedir) < 0)
						errExit("chdir");
				}
			}
		}

		start_application();

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	flush_stdin();
	exit(0);
}
Ejemplo n.º 7
0
int guts(int accept_fd, int listen_fd) {
  
  char buffer[RECV_WINDOW] = "";   // recv buffer
  int msgbuflen = MSG_SIZE;
  char status_msg[MSG_SIZE];
  char *msg; // Incoming message.
  char *send_msg; // Outgoing message.
  char *tmp_msg;
  void *msg_cursor;
  struct response_struct response;   
  int msglen = 0; // length of the assembled message that we receive.
  int recvlen = 0; // how many bytes recv call returns.
  int responselen = 0;   
  int offset;
  int retval;
  char* token_vector[MAX_ARGS] = {'\0'};
  int token_count = 0;

  // Re-register the sigterm handler to our cleanup function.
  signal(SIGTERM, sigterm_handler_child);
  close(listen_fd); // Close this resource from our parent. We don't need it any more.

  while (1) {

    msglen = 0;
    msgbuflen = MSG_SIZE;
    msg = malloc(sizeof(char) * msgbuflen);
    msg_cursor = (void*)msg;
    bzero(msg, msgbuflen);


    // Wait for some data
    while (((recvlen = recv(accept_fd, (void*)buffer, RECV_WINDOW, MSG_PEEK)) == -1) && (errno == EAGAIN));
    if (recvlen == 0) {
      fprintf(stderr, "Client closed the connection.\n");
      close(accept_fd);
      cleanup_and_exit(0);
    };

    // Receive data from our buffered stream until we would block.
    while ((recvlen = recv(accept_fd, (void*)buffer, RECV_WINDOW, 0)) != -1) {
      if (recvlen == 0) {
        fprintf(stderr, "Client closed the connection.\n");
        close(accept_fd);
        cleanup_and_exit(0);
      };

      if (recvlen == -1) {
        fprintf(stderr, "Got error %d from recv.\n", errno);
        close(accept_fd);
        cleanup_and_exit(-1);
      };

      // Extend our message buffer if need be.
      if ((msglen += recvlen) > (msgbuflen)) {
        msgbuflen += msgbuflen;
        offset = msg_cursor - (void*)msg;
        tmp_msg = malloc(sizeof(char) * msgbuflen);
        bzero(tmp_msg, msgbuflen);
        memcpy(tmp_msg, msg, offset);
        msg_cursor = tmp_msg + offset;
        free(msg);
        msg = tmp_msg;
        fprintf(stderr, "msgbuflen expanded to %d\n", msgbuflen);
      }

      memcpy(msg_cursor, (void*)buffer, recvlen);
      msg_cursor += recvlen;
      if (memchr((void*)buffer, '\n', recvlen)) break; // Got a terminator character. Go process our message.

    } 

    tmp_msg = msg;
    strsep(&tmp_msg, "\r\n");

    token_count = tokenize_command(msg, token_vector);

    switch (extract_command(token_vector, token_count))  {

      case 0: // quit
        cleanup_and_exit();
        break;

      case 1: // create
        response = create_command(token_vector, token_count);
        break;

      case 2: // read
        response = read_command(token_vector, token_count);
        break;

      case 3: // delete
        response = delete_command(token_vector, token_count);
        break;

      case 4: // subkeys
        response = keys_command(token_vector, token_count);
        break;

      default:
        if ((response.msg = malloc(sizeof(char) * MSG_SIZE)) == NULL) {
          perror(NULL);
          cleanup_and_exit; 
        }
        bzero(response.msg, MSG_SIZE);
        sprintf(response.msg, "Unknown command.");
        response.status = 1;      
    }

    responselen = prepare_send_msg(response, &send_msg);

    if((send(accept_fd, (void*)send_msg, responselen, 0) == -1)) perror("Send failed");
    free(msg);
    free(response.msg);
    free(send_msg);

  };

  return(0);
}
Ejemplo n.º 8
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();

	pid_t parent = pid;
	// in case the pid is that of a firejail process, use the pid of the first child process
	pid = switch_to_child(pid);

	// now check if the pid belongs to a firejail sandbox
	if (invalid_sandbox(pid)) {
		fprintf(stderr, "Error: no valid sandbox\n");
		exit(1);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	extract_x11_display(parent);

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_nonewprivs(pid);  // redundant on Linux >= 4.10; duplicated in function extract_caps
		extract_caps(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}

	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);

	// set umask, also uid 0
	extract_umask(pid);

	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc") ||
		    join_namespace(pid, "net") ||
		    join_namespace(pid, "pid") ||
		    join_namespace(pid, "uts") ||
		    join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// drop discretionary access control capabilities for root sandboxes
		caps_drop_dac_override();

		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");

		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}

		EUID_USER();
		if (chdir("/") < 0)
			errExit("chdir");
		if (cfg.homedir) {
			struct stat s;
			if (stat(cfg.homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(cfg.homedir) < 0)
					errExit("chdir");
			}
		}

		// set caps filter
		EUID_ROOT();
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		if (getuid() != 0)
			seccomp_load_file_list();
#endif

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);

			// user namespace resets capabilities
			// set caps filter
			if (apply_caps == 1)	// not available for uid 0
				caps_set(caps);
		}

		// set nonewprivs
		if (arg_nonewprivs == 1) {	// not available for uid 0
			int rv = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
			if (arg_debug && rv == 0)
				printf("NO_NEW_PRIVS set\n");
		}

		EUID_USER();
		int cwd = 0;
		if (cfg.cwd) {
			if (chdir(cfg.cwd) == 0)
				cwd = 1;
		}

		if (!cwd) {
			if (chdir("/") < 0)
				errExit("chdir");
			if (cfg.homedir) {
				struct stat s;
				if (stat(cfg.homedir, &s) == 0) {
					/* coverity[toctou] */
					if (chdir(cfg.homedir) < 0)
						errExit("chdir");
				}
			}
		}

		// drop privileges
		drop_privs(arg_nogroups);

		// kill the child in case the parent died
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);

		extract_command(argc, argv, index);
		if (cfg.command_line == NULL) {
			assert(cfg.shell);
			cfg.command_line = cfg.shell;
			cfg.window_title = cfg.shell;
		}
		if (arg_debug)
			printf("Extracted command #%s#\n", cfg.command_line);

		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();

		// set nice value
		if (arg_nice)
			set_nice(cfg.nice);

		// add x11 display
		if (display) {
			char *display_str;
			if (asprintf(&display_str, ":%d", display) == -1)
				errExit("asprintf");
			setenv("DISPLAY", display_str, 1);
			free(display_str);
		}

		start_application(0, NULL);

		// it will never get here!!!
	}

	int status = 0;
	//*****************************
	// following code is signal-safe

	install_handler();

	// wait for the child to finish
	waitpid(child, &status, 0);

	// restore default signal action
	signal(SIGTERM, SIG_DFL);

	// end of signal-safe code
	//*****************************
	flush_stdin();

	if (WIFEXITED(status)) {
		status = WEXITSTATUS(status);
	} else if (WIFSIGNALED(status)) {
		status = WTERMSIG(status);
	} else {
		status = 0;
	}

	exit(status);
}
Ejemplo n.º 9
0
int digest_user_comand(char *msg) 
{
	cmd_t cmd = extract_command(msg);
	char buf[sizeof(info_clients)];

	/* Eventuale argumente ale comenzilor */
	char arg1[NAME_LEN];
	char arg2[NAME_LEN];
	memset(arg1, '\0', NAME_LEN);
	memset(arg2, '\0', NAME_LEN);

	if(cmd == infoclients) {
		int x = send(sockfd, msg, strlen(msg), 0);
		memset(buf, '\0', sizeof(info_clients));

		x = recv(sockfd, buf, sizeof(info_clients), 0);

		struct info_clients *X = (struct info_clients *)buf;
		log_file << client_name << "> infoclients\n";
		for(int i = 0; i < X->nr; ++i) {
			log_file  << X->clients[i].name << " " << X->clients[i].IP << " " << X->clients[i].port << "\n";
			std::cout << X->clients[i].name << " " << X->clients[i].IP << " " << X->clients[i].port << "\n";
			if( !client_exists(X->clients[i].name) ) {
				struct known_client new_client;
				memset(new_client.basic_info.name, '\0', NAME_LEN);
				sprintf(new_client.basic_info.name, "%s", X->clients[i].name);

				memset(new_client.basic_info.IP, '\0', NAME_LEN);
				sprintf(new_client.basic_info.IP, "%s", X->clients[i].IP);

				new_client.basic_info.port = X->clients[i].port;
				new_client.nr_of_shared_files = 0;

				known_clients.push_back(new_client);
			}
		}
		memset(buf, '\0', sizeof(info_clients));
		std::cout << "\n";	
	}

	if(cmd == share) {
		extract_arguments(arg1, arg2, msg);
		log_file << client_name << "> " << msg << "\n";

		FILE *f = fopen(arg1, "r");
		if( f == NULL ) {
			std::cout << ABSENT_FILE << " : Fisier inexistent\n";
			log_file  << ABSENT_FILE << " : Fisier inexistent\n";
			return 1;
		}
		fclose(f);

		if(nr_of_shared_files >= 32) {
			std::cout << "At depasit numarul maxim de fisiere ce pot fi partajate\n";
			return 0;
		}

		/* Punem in arg 2 dimensiunea fisierului */
		struct stat info;
		lstat(arg1, &info);
		memset(arg2, '\0', NAME_LEN);
		human_readable((double)info.st_size, arg2);

		bool is_new_file = true;

		for(int i = 0; i < nr_of_shared_files; ++i) {
			if( strcmp(arg1, shared[i].name) == 0 ) {
				memset(shared[i].size, '\0', NAME_LEN);
				sprintf(shared[i].size, "%s", arg2);
				is_new_file = false;
				break;
			}
		}

		if( is_new_file ) {
			memset(shared[nr_of_shared_files].name, '\0', NAME_LEN);
			memset(shared[nr_of_shared_files].size, '\0', NAME_LEN);

			sprintf(shared[nr_of_shared_files].name, "%s", arg1);
			sprintf(shared[nr_of_shared_files].size, "%s", arg2);
			nr_of_shared_files++;
		}
		
		memset(msg, '\0', BUFLEN);		
		strcat(msg, "share ");
		strcat(msg, arg1);
		strcat(msg, " ");
		strcat(msg, arg2);
		int x = send(sockfd, msg, BUFLEN, 0);
		
		memset(arg2, '\0', NAME_LEN);
		recv(sockfd, arg2, NAME_LEN, 0);

		std::cout << arg2 << "\n\n";		
		log_file  << arg2 << "\n";
	}

	if( cmd == unshare_file ) {
		extract_arguments(arg1, arg2, msg);
		
		std::cout << client_name << "> unshare " << arg1 << "\n";
		log_file  << client_name << "> unshare " << arg1 << "\n";

		int id = -1;
		for(int i = 0; i < nr_of_shared_files; ++i) {
			if( strcmp(shared[i].name, arg1) == 0 ) {
				id = i;
				break;
			}
		}
		
		if( id == -1 ) {
			std::cout << "-5 : Fisier inexistent\n";
			log_file  << "-5 : Fisier inexistent\n";
			return 0;
		}

		for(int i = id + 1; i < nr_of_shared_files; ++i) {
			/* shared[i - 1] <- shared[i] */
			memset(shared[i - 1].name, '\0', NAME_LEN);
			sprintf(shared[i - 1].name, "%s", shared[i].name);
			memset(shared[i - 1].size, '\0', NAME_LEN);
			sprintf(shared[i - 1].size, "%s", shared[i].size);
		}

		nr_of_shared_files--;

		send(sockfd, msg, strlen(msg), 0);

		log_file  << "Succes\n";
		std::cout << "Succes\n\n";
		
	}

	if( cmd == getshare ) {
		extract_arguments(arg1, arg2, msg);
		
		std::cout << client_name << "> " << msg << "\n";
		log_file  << client_name << "> " << msg << "\n";

		send(sockfd, msg, strlen(msg), 0);

		memset(buf, '\0', NAME_LEN);
		recv(sockfd, buf, NAME_LEN, 0);

		int status;
		sscanf(buf, "%d", &status);

		if(status == ABSENT_CLIENT) {
			std::cout << ABSENT_CLIENT << " : Client inexistent\n";
			log_file  << ABSENT_CLIENT << " : Client inexistent\n";
			return 1;
		}

		memset(buf, '\0', NAME_LEN);
		recv(sockfd, buf, NAME_LEN, 0);

		
		int nr;
		sscanf(buf, "%d", &nr);

		int id = -1;
		for(int i = 0; i < known_clients.size(); ++i) {
			if( strcmp(known_clients[i].basic_info.name, arg1) == 0) id = i;
		}

		if( id != -1) known_clients[id].nr_of_shared_files = nr;

		log_file << nr << "\n";		

		char buf1[sizeof(struct client) * MAX_FILES];
		memset(buf1, '\0', sizeof(struct client) * MAX_FILES);

		recv(sockfd, buf1, sizeof(struct client) * MAX_FILES, 0);
		
		struct client *X = (struct client *)buf1;

		for(int i = 0; i < nr; ++i) {
			std::cout << X->shared[i].name << " " << X->shared[i].size << "\n"; 
			log_file  << X->shared[i].name << " " << X->shared[i].size << "\n";
			if( id != -1 ) {
				memset(known_clients[id].shared[i].name, '\0', NAME_LEN);
				sprintf(known_clients[id].shared[i].name, "%s", X->shared[i].name);

				memset(known_clients[id].shared[i].size, '\0', NAME_LEN);
				sprintf(known_clients[id].shared[i].size, "%s", X->shared[i].size);
			}
		}

	}

	if(cmd == history) {
		
		std::cout << client_name << "> history \n"; 
		log_file  << client_name << "> history \n"; 
		if( age == 0 ) return 0;
		std::cout << age << "\n"; 
		log_file  << age << "\n"; 
		for(int i = 0; i < age; i++) {
			std::cout << H[i] << "\n";
			log_file  << H[i] << "\n";
		}
	}

	if(cmd == NOP) {
		;
	}	
}
Ejemplo n.º 10
0
void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
	extract_command(argc, argv, index);

	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (join_namespace(pid, "ipc"))
		exit(1);
	if (join_namespace(pid, "net"))
		exit(1);
	if (join_namespace(pid, "pid"))
		exit(1);
	if (join_namespace(pid, "uts"))
		exit(1);
	if (join_namespace(pid, "mnt"))
		exit(1);

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
		if (rv == 0)
			printf("changing root to %s\n", rootdir);
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set seccomp filter
		if (apply_seccomp == 1)
			seccomp_set();
#endif


    /* We then load the variables that the original Firejail instance applied
     * to the original Firejail client whose namespace we're joining. */
    load_domain_env_from_chroot_proc();

		// mount user namespace or drop privileges
		if (arg_noroot) {
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);
		}
		else 
			drop_privs(arg_nogroups);

		// set prompt color to green
		//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
		if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
			errExit("setenv");

		// run icmdline trough /bin/bash
		if (cfg.command_line == NULL)
			// replace the process with a regular bash session
			execlp("/bin/bash", "/bin/bash", NULL);
		else {
			// run the command supplied by the user
			int cwd = 0;
			if (cfg.cwd) {
				if (chdir(cfg.cwd) == 0)
					cwd = 1;
			}
			
			if (!cwd) {
				if (chdir("/") < 0)
					errExit("chdir");
				if (cfg.homedir) {
					struct stat s;
					if (stat(cfg.homedir, &s) == 0) {
						if (chdir(cfg.homedir) < 0)
							errExit("chdir");
					}
				}
			}

			char *arg[5];
			arg[0] = "/bin/bash";
			arg[1] = "-c";
			if (arg_debug)
				printf("Starting %s\n", cfg.command_line);
      exechelp_logv("firejail", "Starting %s in sandbox %d\n", cfg.command_line, pid);
			if (!arg_doubledash) {
				arg[2] = cfg.command_line;
				arg[3] = NULL;
			}
			else {
				arg[2] = "--";
				arg[3] = cfg.command_line;
				arg[4] = NULL;
			}
			execvp("/bin/bash", arg);
		}

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	exit(0);
}
Ejemplo n.º 11
0
int
flatpak_run (int      argc,
             char   **argv,
             GError **res_error)
{
  FlatpakCommand *command;
  GError *error = NULL;
  GCancellable *cancellable = NULL;
  g_autofree char *prgname = NULL;
  gboolean success = FALSE;
  const char *command_name = NULL;

  command = extract_command (&argc, argv, &command_name);

  if (!command->fn)
    {
      GOptionContext *context;
      g_autofree char *help;

      context = flatpak_option_context_new_with_commands (commands);

      if (command_name != NULL)
        {
          g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Unknown command '%s'", command_name);
        }
      else
        {
          /* This will not return for some options (e.g. --version). */
          if (flatpak_option_context_parse (context, empty_entries, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, &error))
            {
              g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
                                   "No command specified");
            }
        }

      help = g_option_context_get_help (context, FALSE, NULL);
      g_printerr ("%s", help);

      g_option_context_free (context);

      goto out;
    }

  prgname = g_strdup_printf ("%s %s", g_get_prgname (), command_name);
  g_set_prgname (prgname);

  if (!command->fn (argc, argv, cancellable, &error))
    goto out;

  success = TRUE;
out:
  g_assert (success || error);

  if (error)
    {
      g_propagate_error (res_error, error);
      return 1;
    }
  return 0;
}
Ejemplo n.º 12
0
void command_handler(int connfd) {

    int i;
    int is_pipe;

    int client_id = clients_get_id_from_socket(connfd);

    while(1) {

        is_pipe = FALSE;

        for( i=0 ; i<argc ; i++ ) {

            if(argv[i] && argv[i][0] == '|') {

                int p_n = 1;
                if(strlen(argv[i]) == 1)  p_n = 1;
                else    sscanf(argv[i], "|%d", &p_n);

                is_pipe = TRUE;

                //
                int r;
                char **argv_s = extract_command(i);

                if(DEBUG)   debug_print_command(argv_s, p_n);

                if( (r=fork_and_exec_pipe(connfd, argv_s, p_n)) == EXIT_FAILURE) {
                    return;
                } else if (r != SKIP_SHIFT) {
                    pipe_shift(client_id);
                }

                break;

            }

            if(argv[i] && strlen(argv[i])==1 && argv[i][0] == '>') {

                char *filepath = argv[i+1];
                char **argv_s = extract_command(i);
                if(!filepath)   fprintf(stderr, "filepath error\n");
                if( fork_and_exec_file(connfd, argv_s, filepath) == EXIT_FAILURE ) {
                    return;
                }

                pipe_shift(client_id);
                return;

            }

            if(argv[i] && strlen(argv[i])!=1 && argv[i][0] == '<' && argc == i+1) {

                char **argv_s = extract_command(i);
                int source_id;
                sscanf(argv[i], "<%d", &source_id);

                source_id--;

                if(!fifo_lock_get(source_id, clients_get_id_from_socket(connfd))) {
                    sprintf(send_buff, "*** Error: the pipe #%d->#%d does not exist yet. ***\n", source_id+1, clients_get_id_from_socket(connfd)+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if(!check_client_exist(source_id)) {
                    sprintf(send_buff, "*** Error: user #%d does not exist yet. ***\n", source_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if( fork_and_exec_fifo_in(connfd, argv_s, source_id) == EXIT_FAILURE ) {
                    return;
                } else {
                    fifo_lock_set(source_id, clients_get_id_from_socket(connfd), FALSE);
                    broadcast_cmd_fifo_in(connfd, source_id, original_read_buff);
                }

                return;

            }

            if(argv[i] && strlen(argv[i])!=1 && argv[i][0] == '>' && argc == i+1) {

                char **argv_s = extract_command(i);
                int target_id;
                sscanf(argv[i], ">%d", &target_id);

                target_id --;

                if(fifo_lock_get(clients_get_id_from_socket(connfd), target_id)) {
                    sprintf(send_buff, "*** Error: the pipe #%d->#%d already exists. ***\n", clients_get_id_from_socket(connfd)+1, target_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if(!check_client_exist(target_id)) {
                    sprintf(send_buff, "*** Error: user #%d does not exist yet. ***\n", target_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if( fork_and_exec_fifo_out(connfd, argv_s, target_id) == EXIT_FAILURE ) {
                    return;
                } else {
                    fifo_lock_set(clients_get_id_from_socket(connfd), target_id, TRUE);
                    broadcast_cmd_fifo_out(connfd, target_id, original_read_buff);
                }

                return;

            }

            if(argv[i] && strlen(argv[i])!=1 && (argv[i][0] == '<' || argv[i][0] == '>') && argc != i+1) {

                int target_id, source_id;

                // get target_id, source_id
                if(argv[i][0] == '<') {
                    if(sscanf(argv[i], "<%d", &source_id) != 1) {
                        perror("sscanf");
                        return;
                    }
                    if(sscanf(argv[i+1], ">%d", &target_id) != 1) {
                        perror("sscanf");
                        return;
                    }
                } else {
                    if(sscanf(argv[i], ">%d", &target_id) != 1) {
                        perror("sscanf");
                        return;
                    }
                    if(sscanf(argv[i+1], "<%d", &source_id) != 1) {
                        perror("sscanf");
                        return;
                    }
                }

                if(DEBUG)   fprintf(stderr, "source_id=%d\ttarget_id=%d\n", source_id, target_id);

                target_id--, source_id--;

                char **argv_s = extract_command(i);

                if(!fifo_lock_get(source_id, clients_get_id_from_socket(connfd))) {
                    sprintf(send_buff, "*** Error: the pipe #%d->#%d does not exist yet. ***\n", source_id+1, clients_get_id_from_socket(connfd)+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if(fifo_lock_get(clients_get_id_from_socket(connfd), target_id)) {
                    sprintf(send_buff, "*** Error: the pipe #%d->#%d already exists. ***\n", clients_get_id_from_socket(connfd)+1, target_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if(!check_client_exist(source_id)) {
                    sprintf(send_buff, "*** Error: user #%d does not exist yet. ***\n", source_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if(!check_client_exist(target_id)) {
                    sprintf(send_buff, "*** Error: user #%d does not exist yet. ***\n", target_id+1);
                    write(connfd, send_buff, strlen(send_buff)); 
                    return;
                }

                if( fork_and_exec_fifo_in_out(connfd, argv_s, source_id, target_id) == EXIT_FAILURE ) {
                    return;
                } else {

                    fifo_lock_set(source_id, clients_get_id_from_socket(connfd), FALSE);
                    fifo_lock_set(clients_get_id_from_socket(connfd), target_id, TRUE);

                    broadcast_cmd_fifo_in(connfd, source_id, original_read_buff);
                    broadcast_cmd_fifo_out(connfd, target_id, original_read_buff);

                }

                return;
            }

        }

        if(!is_pipe)    break;

    }

    if(argc == 0)   return;
    if(fork_and_exec_last(connfd, argv) == EXIT_SUCCESS) {
        pipe_shift(client_id);
    }

}