web-dev-qa-db-fra.com

setrlimit échoue avec l'opération non autorisée lors de l'exécution sous valgrind

Il se peut que je manque quelque chose ou que ce ne soit pas le cas, mais la fonction setrlimit échoue systématiquement lorsqu'elle est exécutée sous valgrind

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        if ( setrlimit( RLIMIT_NOFILE, &file_limits ) )
        {
                printf(" Failed  %d", errno );
                perror(" More " );
        }
        else
        {
                printf(" Success ");
        }
        printf("\n");
        return 0;
}

Voici les exemples de pistes

Course normale

sh-4.2# ulimit -H -n
800000
sh-4.2# ulimit -S -n
500000
sh-4.2# ./rlimit
 Success
sh-4.2#

sous valgrind

sh-4.2#
sh-4.2# valgrind ./rlimit
==28974== Memcheck, a memory error detector
==28974== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28974== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==28974== Command: ./rlimit
==28974==
 More : Operation not permitted
 Failed  1
==28974==
==28974== HEAP SUMMARY:
==28974==     in use at exit: 0 bytes in 0 blocks
==28974==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==28974==
==28974== All heap blocks were freed -- no leaks are possible
==28974==
==28974== For counts of detected and suppressed errors, rerun with: -v
==28974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
sh-4.2#

Toute allusion à cela serait géniale. NOTE: Ceci est sur la version 7.4 de CentOS (finale).

Modifications n ° 1

Avec code de travail minimal:

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        setrlimit( RLIMIT_NOFILE, &file_limits ) ;
        perror(" wrong ?? " );
        printf("\n");
        return 0;
}

sorties correspondantes:

[root@localhost kk]# valgrind ./rlimit
==29179== Memcheck, a memory error detector
==29179== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29179== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==29179== Command: ./rlimit
==29179==
 wrong ?? : Operation not permitted

==29179==
==29179== HEAP SUMMARY:
==29179==     in use at exit: 0 bytes in 0 blocks
==29179==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==29179==
==29179== All heap blocks were freed -- no leaks are possible
==29179==
==29179== For counts of detected and suppressed errors, rerun with: -v
==29179== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[root@localhost kk]# ./rlimit
 wrong ?? : Success

ceci faux ?? : Opération non autorisée me rend fou :(

Modifier # 2

Donc, sur la base d’une suggestion, j’ai essayé de récupérer les limites existantes et de voir s’il ya quelque chose qui ne va pas dans cette situation, le comportement dépasse mon entendement.

int main()
{
        const struct rlimit file_limits = { .rlim_cur = 65536, .rlim_max = 65536 };
        struct rlimit limit;
        getrlimit(RLIMIT_NOFILE,&limit);
        printf("%d \n",limit.rlim_max);

        setrlimit( RLIMIT_NOFILE, &file_limits ) ;
        perror(" wrong ?? " );
        printf("\n");

        getrlimit(RLIMIT_NOFILE,&limit);
        printf("%d \n",limit.rlim_max);
        return 0;
}

1ère exécution, la limite est fixée à 65590 et l'exécutable est en mesure de modifier les limites à 65536, à savoir, attendue

[root@localhost kk]# ulimit -n
65590
[root@localhost kk]# ./rlimit
65590
 wrong ?? : Success

65536
[root@localhost kk]#

2e manche, sous valgrind

[root@localhost kk]# ulimit -n
65590
[root@localhost kk]# valgrind ./rlimit
==17595== Memcheck, a memory error detector
==17595== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17595== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17595== Command: ./rlimit
==17595==
65578
 wrong ?? : Operation not permitted

65578
==17595==
==17595== HEAP SUMMARY:
==17595==     in use at exit: 0 bytes in 0 blocks
==17595==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==17595==
==17595== All heap blocks were freed -- no leaks are possible
==17595==
==17595== For counts of detected and suppressed errors, rerun with: -v
==17595== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[root@localhost kk]#

Je suis probablement enclin à dire que valgrind réserve peut-être quelques descripteurs de fichiers pour son utilisation en fonction de la discussion ici disons dans ce cas-ci 12 ?? Fixant ainsi la limite à 65578 ?? Ce qui est encore plus que ce que le programme essaie de réserver 65536.

D'autres suggestions à suivre?

14
u__

De la plage autorisée de fd 0 .. hard_limit, Valgrind réserve un ensemble de fd pour ses propres besoins à la fin de la plage C'est-à-dire. la plage hard_limit - 11 .. hard_limit, .__, puis simule une nouvelle limite stricte qui est hard_limit - 12.

Il interdit ensuite à l’invité invité de changer cette limite dure (simulée) . Voici le code qui gère la simulation setrlimit:

 if (((struct vki_rlimit *)(Addr)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
      ((struct vki_rlimit *)(Addr)ARG2)->rlim_max != VG_(fd_hard_limit)) {
     SET_STATUS_Failure( VKI_EPERM );
  }

Comme vous pouvez le constater, si rlim_max fourni est différent de VG_ (fd_hard_limit) simulé, valgrind fait échouer setrlimit . Une fois accepté, valgrind modifiera la limite souple simulée.

Je ne suis pas trop sûr de comprendre pourquoi le code ci-dessus n'accepte pas une limite stricte inférieure et l'installe dans le VG_ simulé (fd_hard_limit) . Je pense que c'est parce que cela (non modifiable) utiliséby valgrind pour trouver la différence entre les fds réservés par valgrind et les fds invités.

Pour contourner le problème, vous devez obtenir la limite, puis ne modifier que la limite logicielle inférieure à la limite fixe, car la modification de la limite fixe sera rejetée par la simulation valgrind setrlimit.

3
phd

Il semble que cela soit l’une des limitations de Valgrind, à savoir une limitation de setrlimit pour la limite stricte lorsqu’elle est exécutée sous Valgrind. Voir dans news pour la version 2.1.2 :

  • Implémenter une limite souple émulée pour les descripteurs de fichier à la zone réservée actuelle, qui agit effectivement comme un dur limite. L'appel système setrlimit met maintenant à jour simplement le fichier émulé limites le mieux possible - la limite stricte ne peut pas bouger et retourne simplement EPERM si vous essayez de le changer. Ceci devrait arrêter les réductions de la limite souple entraînant des assertions lorsque valgrind essaie d’attribuer des descripteurs du domaine réservé. (Ce Provient en fait du bogue n ° 83998).

Notez que vous n'êtes pas le seul à avoir atteint cette limitation de Valgrind. Voir par exemple ce problème de github .

0
ks1322