static void verify_dir_ownership()

in watchman/main.cpp [580:676]


static void verify_dir_ownership(const std::string& state_dir) {
#ifndef _WIN32
  // verify ownership
  struct stat st;
  int dir_fd;
  int ret = 0;
  uid_t euid = geteuid();
  // TODO: also allow a gid to be specified here
  const char* sock_group_name = cfg_get_string("sock_group", nullptr);
  // S_ISGID is set so that files inside this directory inherit the group
  // name
  mode_t dir_perms =
      cfg_get_perms(
          "sock_access", false /* write bits */, true /* execute bits */) |
      S_ISGID;

  auto dirp =
      openDir(state_dir.c_str(), false /* don't need strict symlink rules */);

  dir_fd = dirp->getFd();
  if (dir_fd == -1) {
    log(ERR, "dirfd(", state_dir, "): ", folly::errnoStr(errno), "\n");
    goto bail;
  }

  if (fstat(dir_fd, &st) != 0) {
    log(ERR, "fstat(", state_dir, "): ", folly::errnoStr(errno), "\n");
    ret = 1;
    goto bail;
  }
  if (euid != st.st_uid) {
    log(ERR,
        "the owner of ",
        state_dir,
        " is uid ",
        st.st_uid,
        " and doesn't match your euid ",
        euid,
        "\n");
    ret = 1;
    goto bail;
  }
  if (st.st_mode & 0022) {
    log(ERR,
        "the permissions on ",
        state_dir,
        " allow others to write to it. "
        "Verify that you own the contents and then fix its "
        "permissions by running `chmod 0700 '",
        state_dir,
        "'`\n");
    ret = 1;
    goto bail;
  }

  if (sock_group_name) {
    const struct group* sock_group = w_get_group(sock_group_name);
    if (!sock_group) {
      ret = 1;
      goto bail;
    }

    if (fchown(dir_fd, -1, sock_group->gr_gid) == -1) {
      log(ERR,
          "setting up group '",
          sock_group_name,
          "' failed: ",
          folly::errnoStr(errno),
          "\n");
      ret = 1;
      goto bail;
    }
  }

  // Depending on group and world accessibility, change permissions on the
  // directory. We can't leave the directory open and set permissions on the
  // socket because not all POSIX systems respect permissions on UNIX domain
  // sockets, but all POSIX systems respect permissions on the containing
  // directory.
  logf(DBG, "Setting permissions on state dir to {:o}\n", dir_perms);
  if (fchmod(dir_fd, dir_perms) == -1) {
    logf(
        ERR,
        "fchmod({}, {:o}): {}\n",
        state_dir,
        dir_perms,
        folly::errnoStr(errno));
    ret = 1;
    goto bail;
  }

bail:
  if (ret) {
    exit(ret);
  }
#endif
}