setrlimit失败,在valgrind下运行时不允许操作

u__*_*u__ 14 c linux valgrind centos

我可能会遗漏某些东西或者可能没有,但是setrlimit当在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;
}
Run Code Online (Sandbox Code Playgroud)

以下是样本运行

正常运行

sh-4.2# ulimit -H -n
800000
sh-4.2# ulimit -S -n
500000
sh-4.2# ./rlimit
 Success
sh-4.2#
Run Code Online (Sandbox Code Playgroud)

在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#
Run Code Online (Sandbox Code Playgroud)

对此的任何提示都会很棒.注意:这是在CentOS 7.4版(最终版)上.

编辑#1

使用最少的工作代码:

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

相应的产出:

[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
Run Code Online (Sandbox Code Playgroud)

这个错了?:不允许操作让我抓狂:(

编辑#2

因此,根据一些建议,我试图检索现有的限制,看看是否有什么问题,结果表明我的理解之外的行为

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;
}
Run Code Online (Sandbox Code Playgroud)

第一次运行时,限制设置为65590,可执行文件能够将限制更改为65536,即预期

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

65536
[root@localhost kk]#
Run Code Online (Sandbox Code Playgroud)

第二轮,在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]#
Run Code Online (Sandbox Code Playgroud)

我可能倾向于说可能是valgrind保留一些文件描述符供它使用,基于这里讨论让我们说在这种情况下它12 ?? 因此将限制设置为65578 ?? 这仍然是程序试图保留65536的更多内容.

还有更多建议吗?

phd*_*phd 3

在 fd 0 ..hard_limit 的允许范围中,valgrind 在范围末尾保留一组 fd 以供自己使用,即范围hard_limit - 11 ..hard_limit,然后模拟一个新的硬限制,即hard_limit - 12。

然后,它禁止来宾应用程序更改此(模拟)硬限制。这是处理 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 );
  }
Run Code Online (Sandbox Code Playgroud)

如您所见,如果提供的 rlim_max 与模拟的 VG_(fd_hard_limit) 不同,valgrind 会使 setrlimit 失败。接受后,valgrind 将更改模拟的软限制。

我不太明白为什么上面的代码不接受较低的硬限制并将其设置到模拟的 VG_(fd_hard_limit) 中。我认为这是因为 valgrind 使用这个(不可更改的)VG_(fd_hard_limit) 来查找 valgrind 保留的 fds 和 guest fds 之间的差异。

要绕过该问题,您应该获取限制,然后仅将软限制更改为低于硬限制,因为更改硬限制将被 valgrind setrlimit 模拟拒绝。