コード例 #1
0
ファイル: osquery.cpp プロジェクト: 1514louluo/osquery
static int osquery_ioctl(
    dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) {
#ifdef KERNEL_TEST
  // Reentrant code used for testing the queue functionality.
  // This test-only code allows benchmarks to stress test queue handling.
  static unsigned int test_counter = 0;
  if (cmd == OSQUERY_IOCTL_TEST) {
    if (osquery.buffer == NULL) {
      return -EINVAL;
    }
    test_counter++;

    size_t length = 0;
    void *e = NULL;
    switch (*(int *)data) {
    case 0:
      e = osquery_cqueue_reserve(
          &osquery.cqueue, OSQUERY_TEST_EVENT_0, sizeof(test_event_0_data_t));
      length = 4096;
      break;
    case 1:
      e = osquery_cqueue_reserve(
          &osquery.cqueue, OSQUERY_TEST_EVENT_1, sizeof(test_event_1_data_t));
      length = 33;
      break;
    default:
      return -ENOTTY;
    }
    if (!e) {
      return -EINVAL;
    }

    *(int *)e = test_counter;
    char *s = (char *)((int *)e + 1);
    memset(s, 'H', length);

    osquery_cqueue_commit(&osquery.cqueue, e);

    return 0;
  }
#endif // KERNEL_TEST

  int err = 0;
  osquery_subscription_args_t *sub = NULL;
  osquery_buf_sync_args_t *sync = NULL;
  osquery_buf_allocate_args_t *alloc = NULL;

  // All control should be from a single daemon.
  // Wrap all IOCTL API handling in locks to guarantee proper use.
  lck_mtx_lock(osquery.mtx);
  switch (cmd) {
  // Daemon is requesting a new subscription (e.g., monitored path).
  case OSQUERY_IOCTL_SUBSCRIPTION:
    sub = (osquery_subscription_args_t *)data;
    if ((err = subscribe_to_event(sub->event, sub->subscribe))) {
      goto error_exit;
    }
    break;

  // Daemon is requesting a synchronization of readable queue space.
  case OSQUERY_IOCTL_BUF_SYNC:
    // The queue buffer cannot be synchronized if it has not been allocated.
    if (osquery.buffer == NULL) {
      err = -EINVAL;
      goto error_exit;
    }

    // Unlock while applying update logic, re-lock on error and success.
    lck_mtx_unlock(osquery.mtx);
    sync = (osquery_buf_sync_args_t *)data;
    if ((err = update_user_kernel_buffer(sync->options,
                                         sync->read_offset,
                                         &(sync->max_read_offset),
                                         &(sync->drops)))) {
      lck_mtx_lock(osquery.mtx);
      goto error_exit;
    }
    lck_mtx_lock(osquery.mtx);
    break;

  // Daemon is requesting an allocation for the queue, and shared region.
  case OSQUERY_IOCTL_BUF_ALLOCATE:
    alloc = (osquery_buf_allocate_args_t *)data;
    if (alloc->version != OSQUERY_KERNEL_COMM_VERSION) {
      // Daemon tried connecting with incorrect version number.
      // The structure types and sizes are bound to the COMMs version.
      // Any non-matching daemon may not handle these structures correctly.
      err = -EINVAL;
      goto error_exit;
    }

    if (osquery.buffer != NULL) {
      // There is only a single shared buffer.
      err = -EINVAL;
      goto error_exit;
    }

    // Attempt to allocation and set up the circular queue.
    if ((err = allocate_user_kernel_buffer(alloc->size, &(alloc->buffer)))) {
      goto error_exit;
    }

    dbg_printf(
        "IOCTL alloc: size %lu, location %p\n", alloc->size, alloc->buffer);
    break;
  default:
    err = -ENOTTY;
    goto error_exit;
    break;
  }

error_exit:
  // Unlock and return a status to the daemon.
  lck_mtx_unlock(osquery.mtx);
  return err;
}
コード例 #2
0
ファイル: process_events.c プロジェクト: theopolis/osquery
static int process_cred_label_update_execvew(kauth_cred_t old_cred,
                                             kauth_cred_t new_cred,
                                             struct proc *p,
                                             struct vnode *vp,
                                             off_t offset,
                                             struct vnode *scriptvp,
                                             struct label *vnodelabel,
                                             struct label *scriptvnodelabel,
                                             struct label *execlabel,
                                             u_int *csflags,
                                             void *macpolicyattr,
                                             size_t macpolicyattrlen,
                                             int *disjointp) {
  int path_len = MAXPATHLEN;

  if (!vnode_isreg(vp)) {
    goto error_exit;
  }

  // Determine address of image_params based off of csflags pointer. (HACKY)
  struct image_params *img =
      (struct image_params *)((char *)csflags -
                              offsetof(struct image_params, ip_csflags));

  // Find the length of arg and env we will copy.
  size_t arg_length =
      MIN(MAX_VECTOR_LENGTH, img->ip_endargv - img->ip_startargv);
  size_t env_length = MIN(MAX_VECTOR_LENGTH, img->ip_endenvv - img->ip_endargv);

  osquery_process_event_t *e =
      (osquery_process_event_t *)osquery_cqueue_reserve(
          cqueue,
          OSQUERY_PROCESS_EVENT,
          sizeof(osquery_process_event_t) + arg_length + env_length);

  if (!e) {
    goto error_exit;
  }
  // Copy the arg and env vectors.
  e->argv_offset = 0;
  e->envv_offset = arg_length;

  e->arg_length = arg_length;
  e->env_length = env_length;

  memcpy(&(e->flexible_data[e->argv_offset]), img->ip_startargv, arg_length);
  memcpy(&(e->flexible_data[e->envv_offset]), img->ip_endargv, env_length);

  e->actual_argc = img->ip_argc;
  e->actual_envc = img->ip_envc;

  // Calculate our argc and envc based on the number of null bytes we find in
  // the buffer.
  e->argc = MIN(e->actual_argc,
                str_num(&(e->flexible_data[e->argv_offset]), arg_length));
  e->envc = MIN(e->actual_envc,
                str_num(&(e->flexible_data[e->envv_offset]), env_length));

  e->pid = proc_pid(p);
  e->ppid = proc_ppid(p);
  e->owner_uid = 0;
  e->owner_gid = 0;
  e->mode = -1;
  vfs_context_t context = vfs_context_create(NULL);
  if (context) {
    struct vnode_attr vattr = {0};
    VATTR_INIT(&vattr);
    VATTR_WANTED(&vattr, va_uid);
    VATTR_WANTED(&vattr, va_gid);
    VATTR_WANTED(&vattr, va_mode);
    VATTR_WANTED(&vattr, va_create_time);
    VATTR_WANTED(&vattr, va_access_time);
    VATTR_WANTED(&vattr, va_modify_time);
    VATTR_WANTED(&vattr, va_change_time);

    if (vnode_getattr(vp, &vattr, context) == 0) {
      e->owner_uid = vattr.va_uid;
      e->owner_gid = vattr.va_gid;
      e->mode = vattr.va_mode;
      e->create_time = vattr.va_create_time.tv_sec;
      e->access_time = vattr.va_access_time.tv_sec;
      e->modify_time = vattr.va_modify_time.tv_sec;
      e->change_time = vattr.va_change_time.tv_sec;
    }

    vfs_context_rele(context);
  }

  e->uid = kauth_cred_getruid(new_cred);
  e->euid = kauth_cred_getuid(new_cred);

  e->gid = kauth_cred_getrgid(new_cred);
  e->egid = kauth_cred_getgid(new_cred);

  vn_getpath(vp, e->path, &path_len);

  osquery_cqueue_commit(cqueue, e);
error_exit:

  return 0;
}
コード例 #3
0
ファイル: osquery.cpp プロジェクト: nitish3328/osquery
// All control should be from a single consumer, so we wrap all these calls
// in locks to guarantee proper use.
static int osquery_ioctl(dev_t dev, u_long cmd, caddr_t data,
                         int flag, struct proc *p) {
#ifdef KERNEL_TEST  // Reentrant code used for testing the queue functionality.
    static unsigned int test_counter = 0;
    if (cmd == OSQUERY_IOCTL_TEST) {
        if (osquery.buffer == NULL) {
            return -EINVAL;
        }
        test_counter++;

        size_t length = 0;
        void *e = NULL;
        switch (*(int *)data) {
        case 0:
            e = osquery_cqueue_reserve(&osquery.cqueue, OSQUERY_TEST_EVENT_0,
                                       sizeof(test_event_0_data_t));
            length = 4096;
            break;
        case 1:
            e = osquery_cqueue_reserve(&osquery.cqueue, OSQUERY_TEST_EVENT_1,
                                       sizeof(test_event_1_data_t));
            length = 33;
            break;
        default:
            return -ENOTTY;
        }
        if (!e) {
            return -EINVAL;
        }

        *(int *)e = test_counter;
        char *s = (char *)((int *)e + 1);
        memset(s, 'H', length);

        osquery_cqueue_commit(&osquery.cqueue, e);

        return 0;
    }
#endif // KERNEL_TEST

    lck_mtx_lock(osquery.mtx);

    int err = 0;
    osquery_subscription_args_t *sub = NULL;
    osquery_buf_sync_args_t *sync = NULL;
    osquery_buf_allocate_args_t *alloc = NULL;

    switch (cmd) {
    case OSQUERY_IOCTL_SUBSCRIPTION:
        sub = (osquery_subscription_args_t *)data;
        if ((err = subscribe_to_event(sub->event, sub->subscribe, sub->udata))) {
            goto error_exit;
        }
        break;
    case OSQUERY_IOCTL_BUF_SYNC:
        sync = (osquery_buf_sync_args_t *)data;
        if (osquery.buffer == NULL) {
            err = -EINVAL;
            goto error_exit;
        }
        lck_mtx_unlock(osquery.mtx);
        if ((err = update_user_kernel_buffer(sync->options,
                                             sync->read_offset,
                                             &(sync->max_read_offset),
                                             &(sync->drops)))) {
            lck_mtx_lock(osquery.mtx);
            goto error_exit;
        }
        lck_mtx_lock(osquery.mtx);
        break;
    case OSQUERY_IOCTL_BUF_ALLOCATE:
        alloc = (osquery_buf_allocate_args_t *)data;

        if (alloc->version != OSQUERY_KERNEL_COMM_VERSION) {
            // Daemon tried connecting with incorrect version number.
            err = -EINVAL;
            goto error_exit;
        }

        if (osquery.buffer != NULL) {
            // We don't want to allocate a second buffer.
            err = -EINVAL;
            goto error_exit;
        }

        if ((err = allocate_user_kernel_buffer(alloc->size, &(alloc->buffer)))) {
            goto error_exit;
        }

        dbg_printf("IOCTL alloc: size %lu, location %p\n",
                   alloc->size, alloc->buffer);
        break;
    default:
        err = -ENOTTY;
        goto error_exit;
        break;
    }
error_exit:
    lck_mtx_unlock(osquery.mtx);
    return err;
}