2017-10-16 5 views
0

Je suis actuellement aux prises avec la bonne implémentation d'un noyau-spinlock en combinaison avec une instruction return qui devrait renvoyer une valeur à l'espace utilisateur. Je mis en place un syscall noyau 'sys_kernel_entropy_is_recording' qui renvoie la valeur d'un noyau variable 'is_kernel_entropy_recording':linux syscall utilisant spinlock renvoyant la valeur à l'espace utilisateur

asmlinkage bool sys_kernel_entropy_is_recording(void) 
    { 
     spin_lock(&entropy_analysis_lock); 
     return is_kernel_entropy_recording; 
     spin_unlock(&entropy_analysis_lock); 
    } 

A ce stade, poser deux questions:

Q1: Est-ce la mise en œuvre correcte du tout , ce qui signifie que la valeur correcte de 'is_kernel_entropy_recording' sera retournée à l'espace utilisateur et que le spinlock sera ensuite libéré?

Mes préoccupations sont:

  • a) est-il permis de retourner une valeur de cette userspace à l'espace noyau ainsi du tout?
  • b) l'instruction return est située avant l'instruction spin_unlock, d'où l'appel de spin_unlock?

Q2: Pour répondre à ces question moi-même, je démonte ces la compilé fichier .o mais déterminé (il semble au moins pour moi comme) les appels spin_lock/spin_unlock sont complètement ignorés par le compilateur, car il se déplace juste la valeur de « sys_kernel_entropy_is_recording » à un eax appels ret (je ne suis pas sûr de la ligne « callq 0xA5 »):

(gdb) disassemble /m sys_kernel_entropy_is_recording 
    Dump of assembler code for function sys_kernel_entropy_is_recording: 
    49 { 
     0x00000000000000a0 <+0>: callq 0xa5 <sys_kernel_entropy_is_recording+5> 
     0x00000000000000a5 <+5>: push %rbp 
     0x00000000000000ad <+13>: mov %rsp,%rbp 

    50  spin_lock(&entropy_analysis_lock); 
    51  return is_kernel_entropy_recording; 
    52  spin_unlock(&entropy_analysis_lock); 
    53 } 
     0x00000000000000b5 <+21>: movzbl 0x0(%rip),%eax  # 0xbc <sys_kernel_entropy_is_recording+28> 
     0x00000000000000bc <+28>: pop %rbp 
     0x00000000000000bd <+29>: retq 

Par conséquent, je suppose que l'application de spinlock est incorrect .. quelqu'un pourrait-il me donner un s'il vous plaît des conseils pour une approche appropriée? Merci beaucoup d'avance!

+0

Comme pour le code désassemblé, 'callq' est en fait un appel de fonction. Dans votre cas, il appelle probablement 'spin_lock' (ou, dans le cas où' spin_lock' est une macro ou une fonction inline, il appelle sa fonction interne *). Vous pouvez vérifier cela en demandant à gdb d'appliquer des relocalisations au code désassemblé. Comme pour l'appel 'spin_unlock', le compilateur le trouve probablement * inaccessible * et le supprime simplement. – Tsyvarev

+0

comme une remarque, avez-vous envisagé d'utiliser _atomics_ pour verrouiller une seule variable – myaut

+0

Code après qu'une instruction 'return' est inaccessible. Je suis surpris que vous n'obteniez pas d'avertissement de compilateur (n'est-ce pas?) – Kaz

Répondre

2

Il est interdit de retourner de syscall avec spinlock maintenu. Et, comme d'habitude avec le code C, aucune instruction n'est exécutée après l'instruction return.

La pratique courante est de sauver la valeur obtenue sous les verrous dans variable locale, et la valeur de retour de cette variable après le déblocage:

bool ret; 

spin_lock(&entropy_analysis_lock); 
ret = is_kernel_entropy_recording; 
spin_unlock(&entropy_analysis_lock); 

return ret;