void handle_parent(FILE *input)
{
  char buffer[DEFAULT_BUFFER];
  int i;
  for(i = 0; (fgets(buffer, DEFAULT_BUFFER, input) != NULL); i++)
  {
    write_safe(mapper_pipes[i % NUMBER_MAPPERS][WRITE_END], buffer, DEFAULT_BUFFER);
  }

  // close mapper pipes then wait for mappers to exit
  for(i = 0; i < NUMBER_MAPPERS; i++)
  {
    close_safe(mapper_pipes[i][WRITE_END]);
  }
  int status;
  for(i = 0; i < NUMBER_MAPPERS; i++)
  {
    wait_safe(&status);
  }

  // close reducer pipes then wait for reducers to exit
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    close_safe(reducer_pipes[i][WRITE_END]);
  }
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    wait_safe(&status);
  }
}
void handle_mapper()
{
  char buffer[DEFAULT_BUFFER];
  int i;

  while(read_safe(mapper_pipes[process_number][READ_END], buffer, DEFAULT_BUFFER) > 0)
  {
    for(i = 0; i < strlen(buffer) && buffer[i] != '\n'; i++)
    {
      char letter = buffer[i];
      if((letter >= (int)'a') && (letter <= (int) 'z'))
      {
        int index = (int)letter - (int)'a';
        write_safe(reducer_pipes[index][WRITE_END], &letter, 1);
      }
    }
  }

  for(i = 0; i < NUMBER_MAPPERS; i++)
  {
    close_safe(mapper_pipes[i][READ_END]);
  }
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    close_safe(reducer_pipes[i][WRITE_END]);
  }

  exit(0);
}
Пример #3
0
void context_fini(context_t *ctx)
{
	close_safe(&ctx->fd);
	close_safe(&ctx->dfd);
	close_safe(&ctx->rootfd);
	context_fini_fdset_glob(ctx);
	context_fini_fdset_netns(ctx);
}
Пример #4
0
OrFalse <array <string> > f$file (const string &name) {
  struct stat stat_buf;
  dl::enter_critical_section();//OK
  int file_fd = open_safe (name.c_str(), O_RDONLY);
  if (file_fd < 0) {
    dl::leave_critical_section();
    return false;
  }
  if (fstat (file_fd, &stat_buf) < 0) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  if (!S_ISREG (stat_buf.st_mode)) {
    php_warning ("Regular file expected as first argument in function file, \"%s\" is given", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  size_t size = stat_buf.st_size;
  if (size > string::max_size) {
    php_warning ("File \"%s\" is too large", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }
  dl::leave_critical_section();

  string res ((dl::size_type)size, false);

  dl::enter_critical_section();//OK
  char *s = &res[0];
  if (read_safe (file_fd, s, size) < (ssize_t)size) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  close_safe (file_fd);
  dl::leave_critical_section();

  array <string> result;
  int prev = -1;
  for (int i = 0; i < (int)size; i++) {
    if (s[i] == '\n' || i + 1 == (int)size) {
      result.push_back (string (s + prev + 1, i - prev));
      prev = i;
    }
  }

  return result;
}
Пример #5
0
Файл: util.c Проект: OSLL/pmover
int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd)
{
	int tmp;

	if (old_fd != new_fd) {

		if (!allow_reuse_fd) {
			if (fcntl(new_fd, F_GETFD) != -1 || errno != EBADF) {
				if (new_fd < 3) {
					/*
					 * Standard descriptors.
					 */
					pr_warn("fd %d already in use (called at %s:%d)\n",
						new_fd, file, line);
				} else {
					pr_err("fd %d already in use (called at %s:%d)\n",
						new_fd, file, line);
					return -1;
				}
			}
		}

		tmp = dup2(old_fd, new_fd);
		if (tmp < 0) {
			pr_perror("Dup %d -> %d failed (called at %s:%d)",
				  old_fd, new_fd, file, line);
			return tmp;
		}

		/* Just to have error message if failed */
		close_safe(&old_fd);
	}

	return 0;
}
Пример #6
0
static int prepare_ipc_var(int pid)
{
	int fd, ret;
	IpcVarEntry *var;

	pr_info("Restoring IPC variables\n");
	fd = open_image(CR_FD_IPC_VAR, O_RSTR, pid);
	if (fd < 0)
		return -1;

	ret = pb_read_one(fd, &var, PB_IPC_VAR);
	close_safe(&fd);
	if (ret <= 0) {
		pr_err("Failed to read IPC namespace variables\n");
		return -EFAULT;
	}

	ipc_sysctl_req(var, CTL_PRINT);

	ret = ipc_sysctl_req(var, CTL_WRITE);
	ipc_var_entry__free_unpacked(var, NULL);

	if (ret < 0) {
		pr_err("Failed to prepare IPC namespace variables\n");
		return -EFAULT;
	}

	return 0;
}
void handle_reducer()
{
  char my_letter = (char)((int)'a' + process_number);
  int count = 0;
  char c;

  while(read_safe(reducer_pipes[process_number][READ_END], &c, 1) > 0)
  {
    if(c == my_letter)
    {
      count++;
    }
  }

  printf("count %c:\t%d\n", my_letter, count);
  fflush_safe(stdout);

  int i;
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    close_safe(reducer_pipes[i][READ_END]);
  }

  exit(0);
}
Пример #8
0
Файл: log.c Проект: OSLL/pmover
void log_fini(void)
{
    if (current_logfd > 2)
        close_safe(&current_logfd);

    current_logfd = DEFAULT_LOGFD;
}
Пример #9
0
OrFalse <string> f$file_get_contents (const string &name) {
  if ((int)name.size() == 11 && !memcmp (name.c_str(), "php://input", 11)) {
    return raw_post_data;
  }

  struct stat stat_buf;
  dl::enter_critical_section();//OK
  int file_fd = open_safe (name.c_str(), O_RDONLY);
  if (file_fd < 0) {
    dl::leave_critical_section();
    return false;
  }
  if (fstat (file_fd, &stat_buf) < 0) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  if (!S_ISREG (stat_buf.st_mode)) {
    php_warning ("Regular file expected as first argument in function file_get_contents, \"%s\" is given", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  size_t size = stat_buf.st_size;
  if (size > string::max_size) {
    php_warning ("File \"%s\" is too large", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }
  dl::leave_critical_section();

  string res ((dl::size_type)size, false);

  dl::enter_critical_section();//OK
  if (read_safe (file_fd, &res[0], size) < (ssize_t)size) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  close_safe (file_fd);
  dl::leave_critical_section();
  return res;
}
Пример #10
0
static int check_tty(void)
{
	int master = -1, slave = -1;
	const int lock = 1;
	struct termios t;
	char *slavename;
	int ret = -1;

	if (ARRAY_SIZE(t.c_cc) < TERMIOS_NCC) {
		pr_msg("struct termios has %d @c_cc while "
			"at least %d expected.\n",
			(int)ARRAY_SIZE(t.c_cc),
			TERMIOS_NCC);
		goto out;
	}

	master = open("/dev/ptmx", O_RDWR);
	if (master < 0) {
		pr_perror("Can't open /dev/ptmx");
		goto out;
	}

	if (ioctl(master, TIOCSPTLCK, &lock)) {
		pr_perror("Can't lock pty master");
		goto out;
	}

	slavename = ptsname(master);
	slave = open(slavename, O_RDWR);
	if (slave < 0) {
		if (errno != EIO) {
			pr_perror("Unexpected error on locked pty");
			goto out;
		}
	} else {
		pr_err("Managed to open locked pty.\n");
		goto out;
	}

	ret = 0;
out:
	close_safe(&master);
	close_safe(&slave);
	return ret;
}
Пример #11
0
static void __close_cr_fdset(struct cr_fdset *cr_fdset)
{
	unsigned int i;

	if (!cr_fdset)
		return;

	for (i = 0; i < cr_fdset->fd_nr; i++) {
		if (cr_fdset->_fds[i] == -1)
			continue;
		close_safe(&cr_fdset->_fds[i]);
		cr_fdset->_fds[i] = -1;
	}
}
Пример #12
0
static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
		struct parasite_init_args *args)
{
	int ssock = -1;
	socklen_t sk_len;
	struct sockaddr_un addr;

	pr_info("Putting tsock into pid %d\n", pid);
	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());

	ssock = ctl->ictx.sock;
	sk_len = sizeof(addr);

	if (ssock == -1) {
		pr_err("No socket in ictx\n");
		goto err;
	}

	if (getsockname(ssock, (struct sockaddr *) &addr, &sk_len) < 0) {
		pr_perror("Unable to get name for a socket");
		return -1;
	}

	if (sk_len == sizeof(addr.sun_family)) {
		if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
			pr_perror("Can't bind socket");
			goto err;
		}

		if (listen(ssock, 1)) {
			pr_perror("Can't listen on transport socket");
			goto err;
		}
	}

	/* Check a case when parasite can't initialize a command socket */
	if (ctl->ictx.flags & INFECT_FAIL_CONNECT)
		args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid() + 1);

	/*
	 * Set to -1 to prevent any accidental misuse. The
	 * only valid user of it is accept_tsock().
	 */
	ctl->tsock = -ssock;
	return 0;
err:
	close_safe(&ssock);
	return -1;
}
Пример #13
0
static int prepare_ipc_msg(int pid)
{
	int fd, ret;

	pr_info("Restoring IPC message queues\n");
	fd = open_image(CR_FD_IPCNS_MSG, O_RSTR, pid);
	if (fd < 0)
		return -1;

	while (1) {
		IpcMsgEntry *msq;

		ret = pb_read_one_eof(fd, &msq, PB_IPCNS_MSG_ENT);
		if (ret < 0) {
			pr_err("Failed to read IPC messages queue\n");
			ret = -EIO;
			goto err;
		}
		if (ret == 0)
			break;

		pr_info_ipc_msg_entry(msq);

		ret = prepare_ipc_msg_queue(fd, msq);
		ipc_msg_entry__free_unpacked(msq, NULL);

		if (ret < 0) {
			pr_err("Failed to prepare messages queue\n");
			goto err;
		}
	}
	return close_safe(&fd);
err:
	close_safe(&fd);
	return ret;
}
Пример #14
0
static int prepare_ipc_shm(int pid)
{
	int fd, ret;

	pr_info("Restoring IPC shared memory\n");
	fd = open_image(CR_FD_IPCNS_SHM, O_RSTR, pid);
	if (fd < 0)
		return -1;

	while (1) {
		IpcShmEntry *shm;

		ret = pb_read_one_eof(fd, &shm, PB_IPC_SHM);
		if (ret < 0) {
			pr_err("Failed to read IPC shared memory segment\n");
			ret = -EIO;
			goto err;
		}
		if (ret == 0)
			break;

		pr_info_ipc_shm(shm);

		ret = prepare_ipc_shm_seg(fd, shm);
		ipc_shm_entry__free_unpacked(shm, NULL);

		if (ret < 0) {
			pr_err("Failed to prepare shm segment\n");
			goto err;
		}
	}
	return close_safe(&fd);
err:
	close_safe(&fd);
	return ret;
}
Пример #15
0
static int prepare_ipc_sem(int pid)
{
	int fd, ret;

	pr_info("Restoring IPC semaphores sets\n");
	fd = open_image(CR_FD_IPCNS_SEM, O_RSTR, pid);
	if (fd < 0)
		return -1;

	while (1) {
		IpcSemEntry *sem;

		ret = pb_read_one_eof(fd, &sem, PB_IPC_SEM);
		if (ret < 0) {
			ret = -EIO;
			goto err;
		}
		if (ret == 0)
			break;

		pr_info_ipc_sem_entry(sem);

		ret = prepare_ipc_sem_desc(fd, sem);
		ipc_sem_entry__free_unpacked(sem, NULL);

		if (ret < 0) {
			pr_err("Failed to prepare semaphores set\n");
			goto err;
		}
	}

	return close_safe(&fd);
err:
	close_safe(&fd);
	return ret;
}
Пример #16
0
void files_free_static (void) {
  dl::enter_critical_section();//OK
  if (dl::query_num == opened_files_last_query_num) {
    const array <FILE *> *const_opened_files = opened_files;
    for (array <FILE *>::const_iterator p = const_opened_files->begin(); p != const_opened_files->end(); ++p) {
      if (neq2 (p.get_key(), STDOUT) && neq2 (p.get_key(), STDERR)) {
        fclose (p.get_value());
      }
    }
    opened_files_last_query_num--;
  }

  if (opened_fd != -1) {
    close_safe (opened_fd);
  }

  CLEAR_VAR(string, raw_post_data);
  dl::leave_critical_section();
}
Пример #17
0
static int __sysctl_op(int dir, struct sysctl_req *req, int op)
{
	int fd = -1;
	int ret = -1;
	int nr = 1;

	if (dir >= 0) {
		int flags;

		if (op == CTL_READ)
			flags = O_RDONLY;
		else
			flags = O_WRONLY;

		fd = openat(dir, req->name, flags);
		if (fd < 0) {
			pr_perror("Can't open sysctl %s", req->name);
			return -1;
		}
	}

	switch (CTL_TYPE(req->type)) {
	case __CTL_U32A:
		nr = CTL_LEN(req->type);
	case CTL_U32:
		__SYSCTL_OP(ret, fd, req, u32, nr, op);
		break;
	case __CTL_U64A:
		nr = CTL_LEN(req->type);
	case CTL_U64:
		__SYSCTL_OP(ret, fd, req, u64, nr, op);
		break;
	case __CTL_STR:
		nr = CTL_LEN(req->type);
		__SYSCTL_OP(ret, fd, req, char, nr, op);
		break;
	}

	close_safe(&fd);

	return ret;
}
Пример #18
0
int compel_stop_daemon(struct parasite_ctl *ctl)
{
	if (ctl->daemonized) {
		/*
		 * Looks like a previous attempt failed, we should do
		 * nothing in this case. parasite will try to cure itself.
		 */
		if (ctl->tsock < 0)
			return -1;

		if (parasite_fini_seized(ctl)) {
			close_safe(&ctl->tsock);
			return -1;
		}
	}

	ctl->daemonized = false;

	return 0;
}
Пример #19
0
int sysctl_op(struct sysctl_req *req, size_t nr_req, int op)
{
    int ret = 0;
    int dir = -1;

    dir = open("/proc/sys", O_RDONLY);
    if (dir < 0) {
        pr_perror("Can't open sysctl dir");
        return -1;
    }

    while (nr_req--) {
        ret = __sysctl_op(dir, req, op);
        if (ret < 0)
            break;
        req++;
    }

    close_safe(&dir);

    return ret;
}
void close_pipe_ends()
{
  int i;
  switch (*identifier)
  {
  /* Parent process maintains mapper write and reducer write */
  case PARENT_IDENTIFIER:
    // close mapper read ends and reducer read ends
    for(i = 0; i < NUMBER_MAPPERS; i++)
      close_safe(mapper_pipes[i][READ_END]);
    for(i = 0; i < NUMBER_REDUCERS; i++)
    {
      close_safe(reducer_pipes[i][READ_END]);
      //close(reducer_pipes[i][WRITE_END]);
    }
    break;
  /* Mappers maintain mapper read and reducer write */
  case MAPPER_IDENTIFIER:
    // close mapper write ends and reducer read ends
    for(i = 0; i < NUMBER_MAPPERS; i++)
      close_safe(mapper_pipes[i][WRITE_END]);
    for(i = 0; i < NUMBER_REDUCERS; i++)
      close_safe(reducer_pipes[i][READ_END]);
    break;
  /* Reducers maintain reducer read ends */
  case REDUCER_IDENTIFIER:
    // close mapper read/write ends and reducer write ends
    for(i = 0; i < NUMBER_MAPPERS; i++)
    {
      close_safe(mapper_pipes[i][READ_END]);
      close_safe(mapper_pipes[i][WRITE_END]);
    }
    for(i = 0; i < NUMBER_REDUCERS; i++)
      close_safe(reducer_pipes[i][WRITE_END]);
    break;

  default:
    exit(1);
    break;
  }
}
Пример #21
0
int sysctl_op(struct sysctl_req *req, int op)
{
	int ret = 0;
	int dir = -1;

	if (op != CTL_PRINT && op != CTL_SHOW) {
		dir = open("/proc/sys", O_RDONLY);
		if (dir < 0) {
			pr_perror("Can't open sysctl dir");
			return -1;
		}
	}

	while (req->name) {
		ret = __sysctl_op(dir, req, op);
		if (ret < 0)
			break;
		req++;
	}

	close_safe(&dir);

	return ret;
}
Пример #22
0
static int
start_daemon (pam_handle_t *ph, struct passwd *pwd, const char *password)
{
	struct sigaction defsact, oldsact, ignpipe, oldpipe;
	int inp[2] = { -1, -1 };
	int outp[2] = { -1, -1 };
	int errp[2] = { -1, -1 };
	int ret = PAM_SERVICE_ERR;
	pid_t pid;
	char *output = NULL;
	char *outerr = NULL;
	int failed, status;
	
	assert (pwd);

	/* 
	 * Make sure that SIGCHLD occurs. Otherwise our waitpid below
	 * doesn't work properly. We need to wait on the process to 
	 * get the daemon exit status.
	 */
	memset (&defsact, 0, sizeof (defsact));
	memset (&oldsact, 0, sizeof (oldsact));
	defsact.sa_handler = SIG_DFL;
	sigaction (SIGCHLD, &defsact, &oldsact);
	
	/*
	 * Make sure we don't exit with a SIGPIPE while doing this, that 
	 * would be very annoying to a user trying to log in.
	 */	
	memset (&ignpipe, 0, sizeof (ignpipe));
	memset (&oldpipe, 0, sizeof (oldpipe));
	ignpipe.sa_handler = SIG_IGN;
	sigaction (SIGPIPE, &ignpipe, &oldpipe);
	
	/* Create the necessary pipes */
	if (pipe (inp) < 0 || pipe (outp) < 0 || pipe (errp) < 0) {
	    	syslog (GKR_LOG_ERR, "gkr-pam: couldn't create pipes: %s", 
	    	        strerror (errno));
	    	goto done;
	}

	/* Start up daemon child process */
	switch (pid = fork ()) {
	case -1:
		syslog (GKR_LOG_ERR, "gkr-pam: couldn't fork: %s", 
		        strerror (errno));
		goto done;
		
	/* This is the child */
	case 0:
		setup_child (inp, outp, errp, ph, pwd);
		/* Should never be reached */
		break;
		
	/* This is the parent */
	default:
		break;
	};

	/* Close our unneeded ends of the pipes */
	close (inp[READ_END]);
	close (outp[WRITE_END]);
	close (errp[WRITE_END]);
	inp[READ_END] = outp[WRITE_END] = errp[WRITE_END] = -1; 

	/*
	 * We always pass in a --login argument, even when we have a NULL password
	 * since this controls the startup behavior. When using --login daemon waits
	 * for a password. Closing input signifies password is done.
	 */

	if (password)
		write_string (inp[WRITE_END], password);
	close (inp[WRITE_END]);

	/* 
	 * Note that we're not using select() or any such. We know how the 
	 * daemon sends its data.
	 */

	/* Read any stdout and stderr data */
	output = read_string (outp[READ_END]);
	outerr = read_string (errp[READ_END]);
	if (!output || !outerr) {
		syslog (GKR_LOG_ERR, "gkr-pam: couldn't read data from mate-keyring-daemon: %s", 
		        strerror (errno));
		goto done;
	}

	/* Wait for the initial process to exit */
	if (waitpid (pid, &status, 0) < 0) {
		syslog (GKR_LOG_ERR, "gkr-pam: couldn't wait on mate-keyring-daemon process: %s",
		        strerror (errno));
		goto done;
	}
	
	failed = !WIFEXITED (status) || WEXITSTATUS (status) != 0;
	if (outerr && outerr[0])
		foreach_line (outerr, log_problem, &failed);
	
	/* Failure from process */
	if (failed) {
		syslog (GKR_LOG_ERR, "gkr-pam: mate-keyring-daemon didn't start properly properly");
		goto done;
	}
		
	ret = foreach_line (output, setup_environment, ph);

done:
	/* Restore old handler */
	sigaction (SIGCHLD, &oldsact, NULL);
	sigaction (SIGPIPE, &oldpipe, NULL);
	
	close_safe (inp[0]);
	close_safe (inp[1]);
	close_safe (outp[0]);
	close_safe (outp[1]);
	close_safe (errp[0]);
	close_safe (errp[1]);
	
	free_safe (output);
	free_safe (outerr);

	return ret;
}
Пример #23
0
static int restore_shmem_content(void *addr, struct shmem_info *si)
{
	int fd, fd_pg, ret = 0;

	fd = open_image(CR_FD_SHMEM_PAGEMAP, O_RSTR, si->shmid);
	if (fd < 0) {
		fd_pg = open_image(CR_FD_SHM_PAGES_OLD, O_RSTR, si->shmid);
		if (fd_pg < 0)
			goto err_unmap;
	} else {
		fd_pg = open_pages_image(O_RSTR, fd);
		if (fd_pg < 0)
			goto out_close;
	}

	while (1) {
		unsigned long vaddr;
		unsigned nr_pages;

		if (fd >= 0) {
			PagemapEntry *pe;

			ret = pb_read_one_eof(fd, &pe, PB_PAGEMAP);
			if (ret <= 0)
				break;

			vaddr = (unsigned long)decode_pointer(pe->vaddr);
			nr_pages = pe->nr_pages;

			pagemap_entry__free_unpacked(pe, NULL);
		} else {
			__u64 img_vaddr;

			ret = read_img_eof(fd_pg, &img_vaddr);
			if (ret <= 0)
				break;

			vaddr = (unsigned long)decode_pointer(img_vaddr);
			nr_pages = 1;
		}

		if (vaddr + nr_pages * PAGE_SIZE > si->size)
			break;

		ret = read(fd_pg, addr + vaddr, nr_pages * PAGE_SIZE);
		if (ret != nr_pages * PAGE_SIZE) {
			ret = -1;
			break;
		}

	}

	close_safe(&fd_pg);
	close_safe(&fd);
	return ret;

out_close:
	close_safe(&fd);
err_unmap:
	munmap(addr,  si->size);
	return -1;
}
Пример #24
0
static int parasite_fini_seized(struct parasite_ctl *ctl)
{
	pid_t pid = ctl->rpid;
	user_regs_struct_t regs;
	int status, ret = 0;
	enum trace_flags flag;

	/* stop getting chld from parasite -- we're about to step-by-step it */
	if (restore_child_handler(ctl))
		return -1;

	/* Start to trace syscalls for each thread */
	if (ptrace(PTRACE_INTERRUPT, pid, NULL, NULL)) {
		pr_perror("Unable to interrupt the process");
		return -1;
	}

	pr_debug("Waiting for %d to trap\n", pid);
	if (wait4(pid, &status, __WALL, NULL) != pid) {
		pr_perror("Waited pid mismatch (pid: %d)", pid);
		return -1;
	}

	pr_debug("Daemon %d exited trapping\n", pid);
	if (!WIFSTOPPED(status)) {
		pr_err("Task is still running (pid: %d)\n", pid);
		return -1;
	}

	ret = ptrace_get_regs(pid, &regs);
	if (ret) {
		pr_perror("Unable to get registers");
		return -1;
	}

	if (!task_in_parasite(ctl, &regs)) {
		pr_err("The task is not in parasite code\n");
		return -1;
	}

	ret = compel_rpc_call(PARASITE_CMD_FINI, ctl);
	close_safe(&ctl->tsock);
	if (ret)
		return -1;

	/* Go to sigreturn as closer as we can */
	ret = compel_stop_pie(pid, ctl->sigreturn_addr, &flag,
			ctl->ictx.flags & INFECT_NO_BREAKPOINTS);
	if (ret < 0)
		return ret;

	if (compel_stop_on_syscall(1, __NR(rt_sigreturn, 0),
				__NR(rt_sigreturn, 1), flag))
		return -1;

	if (ptrace_flush_breakpoints(pid))
		return -1;

	/*
	 * All signals are unblocked now. The kernel notifies about leaving
	 * syscall before starting to deliver signals. All parasite code are
	 * executed with blocked signals, so we can sefly unmap a parasite blob.
	 */

	return 0;
}
Пример #25
0
static int parasite_init(struct parasite_ctl *ctl, pid_t pid, int nr_threads)
{
	struct parasite_init_args *args;
	static int sock = -1;

	args = parasite_args(ctl, struct parasite_init_args);

	pr_info("Putting tsock into pid %d\n", pid);
	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
	args->p_addr_len = gen_parasite_saddr(&args->p_addr, pid);
	args->nr_threads = nr_threads;

	if (sock == -1) {
		int rst = -1;

		if (current_ns_mask & CLONE_NEWNET) {
			pr_info("Switching to %d's net for tsock creation\n", pid);

			if (switch_ns(pid, &net_ns_desc, &rst))
				return -1;
		}

		sock = socket(PF_UNIX, SOCK_DGRAM, 0);
		if (sock < 0)
			pr_perror("Can't create socket");

		if (rst > 0 && restore_ns(rst, &net_ns_desc) < 0)
			return -1;
		if (sock < 0)
			return -1;

		if (bind(sock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
			pr_perror("Can't bind socket");
			goto err;
		}

	} else {
		struct sockaddr addr = { .sa_family = AF_UNSPEC, };

		/*
		 * When the peer of a dgram socket dies the original socket
		 * remains in connected state, thus denying any connections
		 * from "other" sources. Unconnect the socket by hands thus
		 * allowing for parasite to connect back.
		 */

		if (connect(sock, &addr, sizeof(addr)) < 0) {
			pr_perror("Can't unconnect");
			goto err;
		}
	}

	if (parasite_execute(PARASITE_CMD_INIT, ctl) < 0) {
		pr_err("Can't init parasite\n");
		goto err;
	}

	if (connect(sock, (struct sockaddr *)&args->p_addr, args->p_addr_len) < 0) {
		pr_perror("Can't connect a transport socket");
		goto err;
	}

	ctl->tsock = sock;
	return 0;
err:
	close_safe(&sock);
	return -1;
}
Пример #26
0
int get_shmem_fd(int pid, VmaEntry *vi)
{
	struct shmem_info *si;
	void *addr = MAP_FAILED;
	int f = -1;
	int flags;

	si = find_shmem_by_id(vi->shmid);
	pr_info("Search for 0x%016"PRIx64" shmem 0x%"PRIx64" %p/%d\n", vi->start, vi->shmid, si, si ? si->pid : -1);
	if (!si) {
		pr_err("Can't find my shmem 0x%016"PRIx64"\n", vi->start);
		return -1;
	}

	if (si->pid != pid)
		return shmem_wait_and_open(pid, si);

	if (si->fd != -1)
		return dup(si->fd);

	flags = MAP_SHARED;
	if (kdat.has_memfd) {
		f = sys_memfd_create("", 0);
		if (f < 0) {
			pr_perror("Unable to create memfd");
			goto err;
		}

		if (ftruncate(f, si->size)) {
			pr_perror("Unable to truncate memfd");
			goto err;
		}
		flags |= MAP_FILE;
	} else
		flags |= MAP_ANONYMOUS;

	/*
	 * The following hack solves problems:
	 * vi->pgoff may be not zero in a target process.
	 * This mapping may be mapped more then once.
	 * The restorer doesn't have snprintf.
	 * Here is a good place to restore content
	 */
	addr = mmap(NULL, si->size, PROT_WRITE | PROT_READ, flags, f, 0);
	if (addr == MAP_FAILED) {
		pr_err("Can't mmap shmid=0x%"PRIx64" size=%ld\n",
				vi->shmid, si->size);
		goto err;
	}

	if (restore_shmem_content(addr, si) < 0) {
		pr_err("Can't restore shmem content\n");
		goto err;
	}

	if (f == -1) {
		f = open_proc_rw(getpid(), "map_files/%lx-%lx",
				(unsigned long) addr,
				(unsigned long) addr + si->size);
		if (f < 0)
			goto err;
	}
	munmap(addr, si->size);

	si->fd = f;

	/* Send signal to slaves, that they can open fd for this shmem */
	futex_inc_and_wake(&si->lock);
	/*
	 * All other regions in this process will duplicate
	 * the file descriptor, so we don't wait them.
	 */
	futex_wait_until(&si->lock, si->count - si->self_count + 1);

	return f;
err:
	if (addr != MAP_FAILED)
		munmap(addr, si->size);
	close_safe(&f);
	return -1;
}
Пример #27
0
Файл: log.c Проект: OSLL/pmover
void log_closedir(void)
{
    close_safe(&logdir);
}
Пример #28
0
int cr_service(bool daemon_mode)
{
	int server_fd = -1;
	int child_pid;

	struct sockaddr_un client_addr;
	socklen_t client_addr_len;

	{
		struct sockaddr_un server_addr;
		socklen_t server_addr_len;

		server_fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
		if (server_fd == -1) {
			pr_perror("Can't initialize service socket");
			goto err;
		}

		memset(&server_addr, 0, sizeof(server_addr));
		memset(&client_addr, 0, sizeof(client_addr));
		server_addr.sun_family = AF_LOCAL;

		if (opts.addr == NULL) {
			pr_warn("Binding to local dir address!\n");
			opts.addr = CR_DEFAULT_SERVICE_ADDRESS;
		}

		strcpy(server_addr.sun_path, opts.addr);

		server_addr_len = strlen(server_addr.sun_path)
				+ sizeof(server_addr.sun_family);
		client_addr_len = sizeof(client_addr);

		unlink(server_addr.sun_path);

		if (bind(server_fd, (struct sockaddr *) &server_addr,
						server_addr_len) == -1) {
			pr_perror("Can't bind");
			goto err;
		}

		pr_info("The service socket is bound to %s\n", server_addr.sun_path);

		/* change service socket permissions, so anyone can connect to it */
		if (chmod(server_addr.sun_path, 0666)) {
			pr_perror("Can't change permissions of the service socket");
			goto err;
		}

		if (listen(server_fd, 16) == -1) {
			pr_perror("Can't listen for socket connections");
			goto err;
		}
	}

	if (daemon_mode) {
		if (daemon(1, 0) == -1) {
			pr_perror("Can't run service server in the background");
			goto err;
		}
	}

	if (opts.pidfile) {
		if (write_pidfile(getpid()) == -1) {
			pr_perror("Can't write pidfile");
			goto err;
		}
	}

	if (setup_sigchld_handler())
		goto err;

	while (1) {
		int sk;

		pr_info("Waiting for connection...\n");

		sk = accept(server_fd, &client_addr, &client_addr_len);
		if (sk == -1) {
			pr_perror("Can't accept connection");
			goto err;
		}

		pr_info("Connected.\n");
		child_pid = fork();
		if (child_pid == 0) {
			int ret;

			if (restore_sigchld_handler())
				exit(1);

			close(server_fd);
			init_opts();
			ret = cr_service_work(sk);
			close(sk);
			exit(ret != 0);
		}

		if (child_pid < 0)
			pr_perror("Can't fork a child");

		close(sk);
	}

err:
	close_safe(&server_fd);

	return 1;
}
Пример #29
0
static int __userns_sysctl_op(void *arg, int proc_fd, pid_t pid)
{
	int fd, ret = -1, dir, i, status, *fds = NULL;
	struct sysctl_userns_req *userns_req = arg;
	int op = userns_req->op;
	struct sysctl_req *req, **reqs = NULL;
	sigset_t blockmask, oldmask;
	pid_t worker;

	// fix up the pointer
	req = userns_req->reqs = (struct sysctl_req *) &userns_req[1];

	/* For files in the IPC/UTS namespaces, restoring is more complicated
	 * than for net. Unprivileged users cannot even open these files, so
	 * they must be opened by usernsd. However, the value in the kernel is
	 * changed for the IPC/UTS namespace that write()s to the open sysctl
	 * file (not who opened it). So, we must set the value from inside the
	 * usernsd caller's namespace. We:
	 *
	 * 1. unsd opens the sysctl files
	 * 2. forks a task
	 * 3. setns()es to the UTS/IPC namespace of the caller
	 * 4. write()s to the files and exits
	 */
	dir = open("/proc/sys", O_RDONLY, O_DIRECTORY);
	if (dir < 0) {
		pr_perror("Can't open sysctl dir");
		return -1;
	}

	fds = xmalloc(sizeof(int) * userns_req->nr_req);
	if (!fds)
		goto out;

	reqs = xmalloc(sizeof(struct sysctl_req) * userns_req->nr_req);
	if (!reqs)
		goto out;

	memset(fds, -1, sizeof(int) * userns_req->nr_req);

	for (i = 0; i < userns_req->nr_req; i++)  {
		int arg_len = sysctl_userns_arg_size(req->type);
		int name_len = strlen((char *) &req[1]) + 1;
		int total_len = sizeof(*req) + arg_len + name_len;
		int flags;

		/* fix up the pointers */
		req->name = (char *) &req[1];
		req->arg = req->name + name_len;

		if (((char *) req) + total_len >= ((char *) userns_req) + MAX_UNSFD_MSG_SIZE) {
			pr_err("bad sysctl req %s, too big: %d\n", req->name, total_len);
			goto out;
		}

		if (op == CTL_READ)
			flags = O_RDONLY;
		else
			flags = O_WRONLY;

		fd = openat(dir, req->name, flags);
		if (fd < 0) {
			if (errno == ENOENT && (req->flags & CTL_FLAGS_OPTIONAL))
				continue;
			pr_perror("Can't open sysctl %s", req->name);
			goto out;
		}

		/* save a pointer to the req, so we don't need to recompute its
		 * location
		 */
		reqs[i] = req;
		fds[i] = fd;

		req = (struct sysctl_req *) (((char *) req) + total_len);
	}

	/*
	 * Don't let the sigchld_handler() mess with us
	 * calling waitpid() on the exited worker. The
	 * same is done in cr_system().
	 */

	sigemptyset(&blockmask);
	sigaddset(&blockmask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &blockmask, &oldmask);

	worker = fork();
	if (worker < 0)
		goto out;

	if (!worker) {
		int nsfd;
		const char *nsname = ns_to_string(userns_req->ns);

		BUG_ON(!nsname);
		nsfd = openat(proc_fd, nsname, O_RDONLY);
		if (nsfd < 0) {
			pr_perror("failed to open pid %d's ns %s", pid, nsname);
			exit(1);
		}

		if (setns(nsfd, 0) < 0) {
			pr_perror("failed to setns to %d's ns %s", pid, nsname);
			exit(1);
		}

		close(nsfd);

		for (i = 0; i < userns_req->nr_req; i++) {
			if (do_sysctl_op(fds[i], reqs[i], op) < 0)
				exit(1);
		}

		exit(0);
	}

	if (waitpid(worker, &status, 0) != worker) {
		pr_perror("worker didn't die?");
		kill(worker, SIGKILL);
		goto out;
	}
	sigprocmask(SIG_SETMASK, &oldmask, NULL);

	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
		pr_err("worker failed: %d\n", status);
		goto out;
	}

	ret = 0;

out:
	if (fds) {
		for (i = 0; i < userns_req->nr_req; i++) {
			if (fds[i] < 0)
				break;
			close_safe(&fds[i]);
		}

		xfree(fds);
	}

	if (reqs)
		xfree(reqs);

	close_safe(&dir);

	return ret;
}