Пример #1
0
struct dir *dir_openat(struct dir *top_dir, const char *dirname)
{
	struct dir *dir = _dir_new(top_dir->db, top_dir->pathname, dirname);
	dir->dir = opendirat(top_dir->dir, dirname);
	int r = (dir->dir != NULL) ? 0 : -1;
	DIRTRACE(dir, r, "opendirat(\"%s\")", dir->pathname);
	if (r == -1) {
		r = mkdirat(dirfd(top_dir->dir), dirname, 0700);
		DIRTRACE(dir, r, "mkdirat(\"%s\")", dir->pathname);
		if (r == 0) {
			dir->dir = opendirat(top_dir->dir, dirname);
			r = (dir->dir != NULL) ? 0 : -1;
			DIRTRACE(dir, r, "opendirat(\"%s\")", dir->pathname);
		}
		if (r == -1) {
			dir_free(dir);
			return NULL;
		}
	}
	return dir;
}
Пример #2
0
bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) {
  bool already_found = false;

  DIR* proc = opendir("/proc");
  if (!proc)
    return false;

  const uid_t uid = getuid();
  struct dirent* dent;
  while ((dent = readdir(proc))) {
    char* endptr = NULL;
    errno = 0;
    const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10);
    if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0)
      continue;

    // We have this setuid code here because the zygote and its children have
    // /proc/$pid/fd owned by root. While scanning through /proc, we add this
    // extra check so users cannot accidentally gain information about other
    // users' processes. To determine process ownership, we use the property
    // that if user foo owns process N, then /proc/N is owned by foo.
    int proc_pid_fd = -1;
    {
      char buf[256];
      struct stat statbuf;
      snprintf(buf, sizeof(buf), "/proc/%lu", pid_ul);
      proc_pid_fd = open(buf, O_RDONLY | O_DIRECTORY);
      if (proc_pid_fd < 0)
        continue;
      if (fstat(proc_pid_fd, &statbuf) < 0 || uid != statbuf.st_uid) {
        close(proc_pid_fd);
        continue;
      }
    }

    DIR* fd = opendirat(proc_pid_fd, "fd");
    if (!fd) {
      close(proc_pid_fd);
      continue;
    }

    while ((dent = readdir(fd))) {
      char buf[256];
      int printed = snprintf(buf, sizeof(buf), "fd/%s", dent->d_name);
      if (printed < 0 || printed >= (int)(sizeof(buf) - 1)) {
        continue;
      }

      ino_t fd_inode;
      if (ProcPathGetInodeAt(&fd_inode, proc_pid_fd, buf)) {
        if (fd_inode == socket_inode) {
          if (already_found) {
            closedir(fd);
            close(proc_pid_fd);
            closedir(proc);
            return false;
          }

          already_found = true;
          *pid_out = pid_ul;
          break;
        }
      }
    }
    closedir(fd);
    close(proc_pid_fd);
  }
  closedir(proc);

  return already_found;
}