Newsgroup: it.comp.os.linux.development
Titolo: Device /dev/mem: accesso da utente non root

Ho la necessità, in una macchina fortemente embedded, di accedere da un 
utente non root ad un'area di memoria ram statica, fisicamente separata 
dalla memoria dinamica. Per questioni di velocità non posso passare da 
un applicazione che a livello di root gestisca la suddetta area di 
memoria ma devo farlo direttamente dalla mia applicazione "non root".
 
NON mi interessa il creare un possibile buco nella protezione del 
sistema: ma non voglio far girare la mia applicazione come root.
 
Pensavo di modificare i source del kernel per togliere questo vincolo 
alla sola /dev/mem o fare una nuova device per accedere alla memoria 
scavalcando /dev/mem, ma credo che comunque il kernel mi chiuda questa 
strada.
 
-Sapete di #define che gestiscono questi blocchi ?
-In quali moduli sorgente del kernel viene gestita la protezione o 
l'accesso alla memoria ?
-Qualche nome di variabile o.... qualcosa da cui iniziare la mia ricerca 
nei meandri del kernel ?
 
T'enchiù.
 
M.
 


Non mi pare una buona soluzione: devi sempre passare per la
MMU in ogni caso e se devi passare per la MMU, e' inutile e
pericoloso bypassare il kernel.
Se i normali meccanismi di memory map non ti bastano
per qualche motivo(Ma non mi pare il tuo caso!), non è
difficile creare un 'driver' che permetta da fare un memory
map nello spazio utente del tuo segmento di memoria e realizzare
quello che vuoi, senza modifiche al kernel.
A.
 
 
 

e allora....
E' possibile avviare una applicazione come root che ottenga da /dev/mem 
un'area di memoria, impegniarla con mmap e condivida poi con una seconda 
applicazione che funzioni come "utente pippo" ?
 
Ipotizzo che il ritorno di mmap non possa essere scambiato tra 
l'applicazione che gira come "root" e l'applicazione che gira come 
"pippo", per esempio tramite un files su disco, giusto ?
 
E allora... come fare ?
 
Mi date qualche dritta su cosa cercare in rete ?
 
Grazie.
M


 Mi date qualche dritta su cosa cercare in rete ?
 
 
Se non puoi dare diritti di accesso al tuo programma alla tua
risorca o se la tua RAM non è a disposizione del sistema, ovvero
non è un device già presente, allora puoi creare un driver
(caricabile come modulo) che implementa la funzione mmap .
Poi crei un device, ad esempio /dev/myram con diritto di accesso a 
chiunque e la tua applicazione esegue il map della memoria...
 
Vedi:
http://www.scs.ch/~frey/linux/memorymap.html
 
 
 
 
/// APPLICAZIONE: MAPPA LA RAM nello spazio user:
///
	int fd;
	char* pRam;
 
	fd = open("/dev/myram", O_RDWR);
	pRam=(void*)mmap(NULL,
			 RAM_SIZE,	
			 (PROT_WRITE|PROT_READ),
			  MAP_SHARED,
			  fd,0);
	if(MAP_FAILED == pRam)
		exit(-1);
	/// USA LA RAM.....
	memset(pRam, 0, RAM_SIZE);
 
NOTA: se gia' esiste un driver per tua ram,
allora fai la open di quello :-)
 
 
/////////////////////////////////////////////////////////////
DRIVER
 
1. Parti da un driver gia' fatto
2. Svuotalo dalle funzioni che non ti servono
3. Aggiungi/modifica le init, exit setup, open, close etc.
4. Aggiungi una funzione di mappa
5. Puoi implementare anche le funzioni di read, write
    cosi' da accerere alla ram in modo 'classico'
6. e una ioctl, ad esempio per implementare funzioni
    di ritorno di info sulla ram (dimensione max etc.)
 
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 >>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
// tabella delle chiamate fops:
static
struct file_operations lv_myMem_fops={
	.owner  = THIS_MODULE,
	.open   = mymem_io_open,
	.release= mymem_io_release,
	.unlocked_ioctl = mymem_io_ioctrl,
	.read = mymem_io_read,
	.write= mymem_io_write,
	.mmap = mymem_mmap,  ////// <----------
};
 
// Esempio di struttura dati del device
//
typedef struct mymem_io{
	unsigned int opened;	/* Counter of open instances */
	unsigned int major;	/* Device major code 		 */
	unsigned int minor;	/* Device minor code 		 */
	dev_t  	id;		/* Device's assigned ID		*/
	void __iomem*	pRam; 	/* RAM space (per read/write)	*/
	unsigned long	ramStart;/* RAM physical address	*/
	size_t		ramSize; /* RAM size			*/
 
	struct platform_device*	pDev;
/*-------------------------------------------------------------------*/
	struct cdev 	cdev;	/* Standard part of character device */
/*-------------------------------------------------------------------*/
}MYMEM_DEV_T;
 
MYMEM_DEV_T	lv_dev;
 
//
// Esempio di map per l' area di RAM....
//
static
int mymem_mmap(struct file* fd, struct vm_area_struct* vma)
{
	MYMEM_DEV_T*  pDev;	// Struttura dati del driver
 
	// use minor to select from many instance of the
	// device created using mknode (for now, not used)
	unsigned int minor = MINOR(fd->f_dentry->d_inode->i_rdev);
 
   	if(NULL==(pDev = fd->private_data))
	{
		errprintk("mmap.%u: SW FAIL>\n",minor);
	        return(-EBADF);
	}
 
	/*
	 * Map the RAM
	 */
	if((0==pDev->ramStart)||(0==pDev->ramSize))
	{
		errprintk("mmap.%u: RAM not available>\n",minor);
         return(-EBADF);
	}
 
	if((vma->vm_end-vma->vm_start) > (pDev->ramSize) )
	{
		errprintk("mmap.%u: %d Requested NVRAM size too big (max=%d)>\n",minor,
					(vma->vm_end-vma->vm_start),
					(pDev->ramSize));
		return(-EINVAL);
	}
	vma->vm_pgoff = (pDev->ramStart >> PAGE_SHIFT);
 
     if (remap_pfn_range(vma,
		vma->vm_start,
		vma->vm_pgoff,
		(vma->vm_end-vma->vm_start),
		vma->vm_page_prot) != 0)
	{
	errprintk("mmap:%08X.%08X.%08X FAILURE>\n",vma->vm_start, vma->vm_end, 
vma->vm_pgoff );
         return (-EAGAIN);
     }
     vma->vm_file=fd;
     return(0);
}
 
 
/// Mi sembra buona cosa avere anche le chiamate read/write
// a disposizione :-)
//
 
ssize_t mymem_io_read(
struct file* fd,char __user* pBuf, size_t len, loff_t* ptr
)
{
	/// TBD
	/// Implementa la lettura della memoria
	/// e ritorna i dati allo user
	return(0);
}
 
ssize_t tvm400_io_write(
  struct file* fd, const char __user* pBuf, size_t len,loff_t* ppos
)
{
	/// TBD
	/// Implementa la scrittura in memoria
	return(0);
}
 
 

 memoria ma devo farlo direttamente dalla mia applicazione "non root".
 
Usare ramdisk?
 
Nicola.
 
-- 
chi va pian va san e va lontan