Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Mar 2012 20:10:39 +0000
From:      Eric Saint-Etienne <eric.saintetienne@gmail.com>
To:        Ryan Stone <rysto32@gmail.com>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: malloc pages map to user space
Message-ID:  <CACJX%2B5079mShMOyEpgXz8C%2B_M9zui6ew_kGwRHb1tEv_aCpvbA@mail.gmail.com>
In-Reply-To: <CACJX%2B511wZyKVXeYqUQ3v6Uh0ZN83TbBZT7CC6V6N0jTsibD-w@mail.gmail.com>
References:  <CACJX%2B52DPPYea5k6QxQ6WQ62GEA9YHGr4y=ETUpPArNL83kh5w@mail.gmail.com> <CACJX%2B535YeOwWZodE1w8jiECKbDgyBbZgYDd=M31NwyTMTx83g@mail.gmail.com> <CACJX%2B51Po_RfhUF7Ba1VT0XLfLWQYWFmnRBRcNuDp%2B3nh_AopQ@mail.gmail.com> <CAFMmRNxvLz9G73Kn2BXq9WG5-0ZcTN%2BSumawWDzz5DRj=hN4PQ@mail.gmail.com> <CACJX%2B511wZyKVXeYqUQ3v6Uh0ZN83TbBZT7CC6V6N0jTsibD-w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Here is some code which fails with malloc < 1 page
and sometimes succeeds with large mallocs (> 16 pages)

What's wrong?

#include <sys/param.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/resourcevar.h>

// Copyright: skeleton took from an older post on the freebsd list

#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>

MALLOC_DEFINE(M_FIVEG_SYSC, "fiveg_sysc", "fiveg_sysc test");

struct args {
  unsigned char **p;
};

/* String to be located in maped buffer */

#define SIZE PAGE_SIZE // 1 page always fail

static void initialize_array(char *p) {
  int i;

  for (i = 0; i < 26; i++)
    p[i] = i+'a';
  p[26] = '!';
  p[27] = '\0';
}

static vm_offset_t addr; // allocated/freed at module load/unload

/* Syscall func */
static int syscf(struct thread *td, void *sa) {
  vm_offset_t user_addr; /* User space address  */
  struct args *uap = (struct args*) sa;
  struct proc *procp = (struct proc *)td->td_proc;
  struct vmspace *vms = procp->p_vmspace;
  vm_map_t map;
  int result;
  vm_object_t     object;
  vm_ooffset_t    objoffset;
  vm_map_entry_t  entry;
  vm_pindex_t     pindex;
  vm_prot_t       prot;
  boolean_t       wired;

  map = kernel_map; // it always return data within kmeme anyway

  uprintf("KERNEL string is '%s' (%p)\n", (char*) addr, (void*) addr);

  result = vm_map_lookup(&map, addr, VM_PROT_ALL, &entry, &object,
&pindex, &prot, &wired);
  if (result != KERN_SUCCESS) {
    uprintf("KERNEL vm_map_lookup failed (%d)\n", result);
    return ENOMEM;
  }
  vm_map_lookup_done(map, entry);
  if (object == kernel_object) uprintf("object is kernel_object\n");
  else if (object == kmem_object) uprintf("object is kmem_object\n");
  else uprintf("object=%p (not kmem, not kernel)\n", object);
  uprintf("entry=%p\n", entry);

  /* Offset in vm_object */
  objoffset = addr - entry->start + entry->offset;
  user_addr = 0;

  result = vm_map_find(&vms->vm_map, object, objoffset, (vm_offset_t
*) &user_addr, SIZE, VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
  if (result != KERN_SUCCESS)
    uprintf("vm_map_find failed: %d\n", result);
  else {

    *uap->p = (char*) user_addr;
    uprintf("KERNEL ---> Syscall: user_addr for allocating space =
0x%lx\n", user_addr);
  }

  return result;
}

/* Sysent entity for syscall */
static struct sysent sc_sysent = {
  1,     /* Number of arguments */
  syscf  /* Syscall function    */
};


//static struct sysent *old_sysent;

/* Offset in sysent[] */
static int offset = NO_SYSCALL;

/* Loader */
  static int
load (struct module *m, int cmd, void *something)
{
  int error = 0;
  switch(cmd){
    case MOD_LOAD:
      //MALLOC(addr, vm_offset_t, SIZE, M_FIVEG_SYSC, M_WAITOK | M_ZERO);
      addr = (vm_offset_t) malloc(SIZE, M_FIVEG_SYSC, M_WAITOK);
      initialize_array((char*) addr);
      uprintf("KERNEL Module with sysc loaded. Offset = %d \n", offset);
      break;

    case MOD_UNLOAD:
      free((void*) addr, M_FIVEG_SYSC);
      uprintf("KERNEL Module with sysc unloaded. Offset = %d \n", offset);
      break;

    default:
      error = EOPNOTSUPP;
      break;
  }
  return (error);


/* Syscall macro*/
SYSCALL_MODULE(fiveg_sysc, &offset, &sc_sysent, load, NULL);

/* eof */

------------------------------------------------
-- USERLAND PROGRAM
------------------------------------------------


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/module.h>

int main(int argc, char *argv[])
{
  int sysc_num, error;
  struct module_stat mstat;

  /* This Variable will save the addres of remapped buffer */
  unsigned char *some_var = NULL;

  /* Pointer to pointer to remapped buffer */
  unsigned char **p = &some_var;

  /* Search module with system call */
  mstat.version = sizeof(mstat);
  if (!(modstat(modfind("sys/fiveg_sysc"), &mstat))){
    /* Our module */
    sysc_num = mstat.data.intval;
    printf("USER: Module found, Syscall number = %d \n", sysc_num);

    /* make system call */
    error = syscall(sysc_num, p);

    if (error != 0) {
      printf("USER: an error occured: %d\n", error);
      return -1;
    }
    /* Read the string from remapped buffer */
    printf("USER:  p = %p\n", p);
    printf("USER: *p = %p\n", *p);
    printf("USER: String = %s\n", *p);
  } else
    printf("USER: Module seems to be not loaded! \n");

  return 0;
}

/* eof */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CACJX%2B5079mShMOyEpgXz8C%2B_M9zui6ew_kGwRHb1tEv_aCpvbA>