Utilisation de la table de descripteur local (LDT)

J’essaie de faire des expériences en utilisant différents segments en plus du segment de code par défaut et des segments d’utilisateur et de kernel de données. J’espère y parvenir en utilisant la table de descripteurs locaux et l’appel système modify_ldt. Grâce à l’appel système, j’ai créé une nouvelle entrée dans LDT qui est un descripteur de segment avec l’adresse de base d’une variable globale que je souhaite “isoler” et d’une limite de 4 octets.

J’essaie de charger le registre de segment de données avec le sélecteur de segment de mon entrée LDT personnalisée via un assemblage en ligne dans un programme C, mais lorsque j’essaie d’accéder à la variable, un défaut de segmentation se produit.

Je soupçonne qu’il existe un problème avec le décalage de ma variable globale. Lorsque l’adresse est calculée, elle dépasse la limite de mon segment personnalisé, ce qui provoque une erreur de segmentation.

Est-ce que quelqu’un sait d’un travail autour de cette situation?

Oh, au fait, c’est sur une architecture x86 sous Linux. C’est la première fois que je pose une question comme celle-ci sur un forum. Par conséquent, si vous souhaitez obtenir des informations complémentaires, merci de me le faire savoir.

Merci d’avance.

Edit: J’ai réalisé que je devrais probablement inclure le code source 🙂

struct user_desc* table_entry_ptr = NULL; /* Allocates memory for a user_desc struct */ table_entry_ptr = (struct user_desc*)malloc(sizeof(struct user_desc)); /* Fills the user_desc struct which represents the segment for mx */ table_entry_ptr->entry_number = 0; table_entry_ptr->base_addr = ((unsigned long)&mx); table_entry_ptr->limit = 0x4; table_entry_ptr->seg_32bit = 0x1; table_entry_ptr->contents = 0x0; table_entry_ptr->read_exec_only = 0x0; table_entry_ptr->limit_in_pages = 0x0; table_entry_ptr->seg_not_present = 0x0; table_entry_ptr->useable = 0x1; /* Writes a user_desc struct to the ldt */ num_bytes = syscall( __NR_modify_ldt, LDT_WRITE, // 1 table_entry_ptr, sizeof(struct user_desc) ); asm("pushl %eax"); asm("movl $0x7, %eax"); /* 0111: 0-Index 1-Using the LDT table 11-RPL of 3 */ asm("movl %eax, %ds"); asm("popl %eax"); mx = 0x407CAFE; 

Le défaut seg se produit à la dernière instruction.

Je ne peux que deviner, puisque je n’ai pas l’assemblage à ma disposition.

Je devine que la ligne à laquelle vous obtenez une erreur de segmentation est compilée à quelque chose comme:

 mov ds:[offset mx], 0x407cafe 

offset mx est le décalage par rapport à mx dans le segment de données du programme (s’il s’agit d’une variable statique) ou dans la stack (s’il s’agit d’une variable automatique). Quoi qu’il en soit, ce décalage est calculé au moment de la compilation, et c’est ce qui sera utilisé quel que soit le point sur lequel DS pointe.

Maintenant, ce que vous avez fait ici est de créer un nouveau segment dont la base est à l’adresse mx et dont la limite est 0x4 ou 0x4fff (selon le G-bit que vous n’avez pas spécifié).

Si le G-bit est 0x4 0, la limite est fixée à 0x4 , et puisqu’il est hautement improbable que mx soit situé entre les adresses 0x0 et 0x4 du DS origine, lorsque vous accédez au décalage mx dans le nouveau segment, vous dépassez la limite .

Si le G-bit est 1, la limite est 0x4fff . Maintenant, vous obtiendrez une erreur de segmentation uniquement si le mx origine était situé au-dessus de 0x4fff .

Étant donné que la base du nouveau segment est à mx , vous pouvez accéder à mx en procédant comme suit:

 mov ds:[0], 0x407cafe 

Je ne sais pas comment j’écrirais ça en C, cependant.