<commit_before>/*
 * Copyright (c) 2016 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "native_client/src/trusted/service_runtime/sel_ldr_filename.h"

#include <errno.h>
#include <string.h>

#include "native_client/src/include/build_config.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/service_runtime/include/sys/errno.h"
#include "native_client/src/trusted/service_runtime/nacl_copy.h"
#include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"


/*
 * Verifies the path is prefixed by the root directory of the restricted
 * filesystem.
 *
 * @param[in] path The path being checked.
 * @param[in] path_len The length of |path|.
 * @return 0 if path does NOT contain the prefix, else 1.
 */
static int PathContainsRootPrefix(const char *path, size_t path_len) {
  /* The full path must be at least as long as the root to contain it. */
  if (path_len < NaClRootDirLen)
    return 0;
  /* The first 'NaClRootDirLen' bytes must match. */
  if (strncmp(NaClRootDir, path, NaClRootDirLen))
    return 0;
  /* If the root is "/foo", then "/foobar" should be marked as invalid. */
  if (path_len > NaClRootDirLen && path[NaClRootDirLen] != '/')
    return 0;
  return 1;
}

#if !NACL_WINDOWS
/*
 * Given a |virtual_path| (a path supplied by the user with no knowledge of
 * the mounted directory) transform it into an |real_path|, which is either
 * an absolute path prefixed by the root mount directory, or a relative path.
 *
 * @param[in] virtual_path Virtual path supplied by user.
 * @param[out] real_path The real path referenced by the |virtual_path|.
 * @param[in] real_path_size The size of the |real_path| buffer.
 * @return 0 on success, else a negated NaCl errno.
 */
static uint32_t VirtualToRealPath(const char *virtual_path,
                                  char       *real_path,
                                  size_t     real_path_max_size) {
  size_t virtual_path_len = strlen(virtual_path);
  if (virtual_path[0] == '/') {
    /* Absolute Path = Prefix + Absolute Virtual Path + '\0' */
    if (virtual_path_len + NaClRootDirLen + 1 > real_path_max_size) {
      NaClLog(LOG_ERROR, "Pathname too long: %s\n", virtual_path);
      return -NACL_ABI_ENAMETOOLONG;
    }
    /* Prefix */
    strcpy(real_path, NaClRootDir);
    /* Prefix + Virtual Path */
    strcat(real_path, virtual_path);
  } else {
    /* Relative Path = Relative Virtual Path + '\0' */
    if (virtual_path_len + 1 > real_path_max_size) {
      NaClLog(LOG_ERROR, "Pathname too long: %s\n", virtual_path);
      return -NACL_ABI_ENAMETOOLONG;
    }
    strcpy(real_path, virtual_path);
  }

  return 0;
}

/*
 * Determine if |path| points to a symbolic link.
 *
 * @param[in] path Path of file to be checked.
 * @return Nonzero if path is symbolic link.
 */
static int IsSymbolicLink(const char *path) {
  struct stat buf;
  int result = lstat(path, &buf);
  return result == 0 && S_ISLNK(buf.st_mode);
}

/*
 * @param[in] path The path to be verified.
 * @return 0 if the path is valid, else a negated NaCl errno.
 */
static uint32_t ValidatePath(const char *path) {
  if (strstr(path, "..")) {
    NaClLog(LOG_ERROR, "Pathname contains ..: %s\n", path);
    return -NACL_ABI_EACCES;
  }

  if (path[0] == '/')
    CHECK(PathContainsRootPrefix(path, strlen(path)));

  /*
   * This is an informal check, and we still require the users of sel_ldr to
   * ensure that no symbolic links exist in the mounted directory.
   *
   * A race condition exists that can bypass this check:
   * 1) Open (or any file access function) called on a path to a regular
   *    file (PATH_REG). "IsSymbolicLink" returns zero, but the original file
   *    access function has not yet been called.
   * 2) Outside of sel_ldr, a symbolic link is moved into PATH_REG.
   * 3) The original file access function is called on a symbolic link.
   *
   * Thus, we still require the caller of sel_ldr to guarantee that no symbolic
   * links are inside the mounted directory.
   */
  if (IsSymbolicLink(path)) {
    return -NACL_ABI_EACCES;
  }<commit_msg>Reduce relative path error messages to warnings<commit_after>/*
 * Copyright (c) 2016 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "native_client/src/trusted/service_runtime/sel_ldr_filename.h"

#include <errno.h>
#include <string.h>

#include "native_client/src/include/build_config.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/service_runtime/include/sys/errno.h"
#include "native_client/src/trusted/service_runtime/nacl_copy.h"
#include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"


/*
 * Verifies the path is prefixed by the root directory of the restricted
 * filesystem.
 *
 * @param[in] path The path being checked.
 * @param[in] path_len The length of |path|.
 * @return 0 if path does NOT contain the prefix, else 1.
 */
static int PathContainsRootPrefix(const char *path, size_t path_len) {
  /* The full path must be at least as long as the root to contain it. */
  if (path_len < NaClRootDirLen)
    return 0;
  /* The first 'NaClRootDirLen' bytes must match. */
  if (strncmp(NaClRootDir, path, NaClRootDirLen))
    return 0;
  /* If the root is "/foo", then "/foobar" should be marked as invalid. */
  if (path_len > NaClRootDirLen && path[NaClRootDirLen] != '/')
    return 0;
  return 1;
}

#if !NACL_WINDOWS
/*
 * Given a |virtual_path| (a path supplied by the user with no knowledge of
 * the mounted directory) transform it into an |real_path|, which is either
 * an absolute path prefixed by the root mount directory, or a relative path.
 *
 * @param[in] virtual_path Virtual path supplied by user.
 * @param[out] real_path The real path referenced by the |virtual_path|.
 * @param[in] real_path_size The size of the |real_path| buffer.
 * @return 0 on success, else a negated NaCl errno.
 */
static uint32_t VirtualToRealPath(const char *virtual_path,
                                  char       *real_path,
                                  size_t     real_path_max_size) {
  size_t virtual_path_len = strlen(virtual_path);
  if (virtual_path[0] == '/') {
    /* Absolute Path = Prefix + Absolute Virtual Path + '\0' */
    if (virtual_path_len + NaClRootDirLen + 1 > real_path_max_size) {
      NaClLog(LOG_ERROR, "Pathname too long: %s\n", virtual_path);
      return -NACL_ABI_ENAMETOOLONG;
    }
    /* Prefix */
    strcpy(real_path, NaClRootDir);
    /* Prefix + Virtual Path */
    strcat(real_path, virtual_path);
  } else {
    /* Relative Path = Relative Virtual Path + '\0' */
    if (virtual_path_len + 1 > real_path_max_size) {
      NaClLog(LOG_ERROR, "Pathname too long: %s\n", virtual_path);
      return -NACL_ABI_ENAMETOOLONG;
    }
    strcpy(real_path, virtual_path);
  }

  return 0;
}

/*
 * Determine if |path| points to a symbolic link.
 *
 * @param[in] path Path of file to be checked.
 * @return Nonzero if path is symbolic link.
 */
static int IsSymbolicLink(const char *path) {
  struct stat buf;
  int result = lstat(path, &buf);
  return result == 0 && S_ISLNK(buf.st_mode);
}

/*
 * @param[in] path The path to be verified.
 * @return 0 if the path is valid, else a negated NaCl errno.
 */
static uint32_t ValidatePath(const char *path) {
  if (strstr(path, "..")) {
    NaClLog(LOG_WARNING, "Pathname contains ..: %s\n", path);
    return -NACL_ABI_EACCES;
  }

  if (path[0] == '/')
    CHECK(PathContainsRootPrefix(path, strlen(path)));

  /*
   * This is an informal check, and we still require the users of sel_ldr to
   * ensure that no symbolic links exist in the mounted directory.
   *
   * A race condition exists that can bypass this check:
   * 1) Open (or any file access function) called on a path to a regular
   *    file (PATH_REG). "IsSymbolicLink" returns zero, but the original file
   *    access function has not yet been called.
   * 2) Outside of sel_ldr, a symbolic link is moved into PATH_REG.
   * 3) The original file access function is called on a symbolic link.
   *
   * Thus, we still require the caller of sel_ldr to guarantee that no symbolic
   * links are inside the mounted directory.
   */
  if (IsSymbolicLink(path)) {
    return -NACL_ABI_EACCES;
  }
{'fraction_non_alphanumeric': 0.103874883286648, 'fraction_numerical': 0.0063025210084033615, 'mean_word_length': 3.3608142493638677, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4324450', 'n_tokens_mistral': 2874, 'n_tokens_neox': 2758, 'n_words': 936}