• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Probleme mit copy_from_user

ArminI

Newbie
Hallo,
ich möchte mittels coppy_from_user eine Memory Area in einen Kernel Buffer kopieren.

Code:
struct vm_area_struct *vma= find_vma(addr);
	if (!vma)
		return addr;
	unsigned long segment_start=vma->vm_start;
	unsigned long segment_ende= vma->vm_end;
	unsigned long segment_size= segment_ende - segment_start;

	if (access_ok(VERIFY_READ,(void*)segment_start, segment_size) == 0){
		printk("Speicherbereich nicht gültig\n");
		goto out1;
	}else{
		printk("Speicherbereich gültig\n");
	}

	if ((error=copy_from_user( segment_buffer, (void*)segment_start, segment_size))){
		printk ("Fehler copy_from_user error:%d);
		error=ERROR;
	        goto out1;
	}


Zuerst hole ich mir einen Zeiger auf eine vm_area_struct. Anschließen übeprüfe ich den Adressbereich mittels access_ok. Danach versuche ich die Kopieraktion durchzuführen.
Die Funktion copy_from_user gibt aber immer einen Fehler zurück.
Kann mir jemand sagen, unter welchen Bedingungen copy_from_user fehlschlägt ?
Insbesondere wenn der Adressbereich zuvor mittels access_ok getestet wurde. Auserdem bin ich bisher davon ausgegangen, der Adressbereich (vma->end - vma->start) einer vm_area_struct grundsätzlich gültig ist.


Vielen Dank und Grüße

Armin
 
OP
A

ArminI

Newbie
hallo,

habe in einem Kernelmodul den Systemaufruf mmap durch einen eigenen ersetzt und den Original Systemhandler in "mmap_original" gespeichert.
Die Variable addr ist der Rückggabewert von "mmap_original". Dies ist ja immer eine Adresse aus dem user space. Die Variable "segment_buffer" ist auch gültig.

Wie gesagt, was mich wirklich wunder ist, trotz der Überprüfung mittels access_ok der Kopiervorgang scheitert.

Habe es auch schon mit einer Schleife und "get_user" probiert. Die Schleife bricht auch gegen Ende des Adressbereiches ab.

Code:
long (mmap_hook)(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off){

	unsigned long addr= mmap_original(addr,len,prot,flags,fd,off);
        
       struct vm_area_struct *vma= find_vma(current->mm, erg);
	if (!vma)
		return erg;


        .......

    unsigned long segment_start=vma->vm_start;
    unsigned long segment_ende= vma->vm_end;
    unsigned long segment_size= segment_ende - segment_start;

    unsigned char* segment_buffer= (unsigned char*) get_pages_in_byte(segment_size,&order_segment_buffer);

	if (!segment_buffer){
		printk ("Fehler malloc segment_buffer\n");
		return ERROR;
	}


   if (access_ok(VERIFY_READ,(void*)segment_start, segment_size) == 0){
      printk("Speicherbereich nicht gültig\n");
      goto out1;
   }else{
      printk("Speicherbereich gültig\n");
   }

   if ((error=copy_from_user( segment_buffer, (void*)segment_start, segment_size))){
      printk ("Fehler copy_from_user error:%d);
      error=ERROR;
           goto out1;
   }


Armin
 
Oben