【问题标题】:How to solve “access denied” error trying to create a message queue?如何解决尝试创建消息队列的“拒绝访问”错误?
【发布时间】:2021-11-07 17:51:23
【问题描述】:

仅在从 .NET 调用代码时发生。当相同的代码编译为 C++ 控制台应用程序,或从 C++ 控制台应用程序调用时,它运行时不会出错。

以下代码编译从 .NET 调用的 C++ DLL,并打印“mq_open failed, code 1, message Operation not allowed”:

extern "C" __attribute__((visibility("default")))
int mq_test()
{
    const char* name = "/985a8e18-08ee-46e5-acf5-fc4f2ffb4d4f";
    constexpr int oflag = O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL;
    constexpr mode_t mode = 0660;

    mq_attr qa;
    memset( &qa, 0, sizeof( qa ) );
    qa.mq_maxmsg = 10;
    qa.mq_msgsize = sizeof( void* );

    int fd = mq_open( name, oflag, mode, &qa );
    if( fd >= 0 )
    {
        mq_unlink( name );
        printf( "mq_open completed OK\n" );
        return 0;
    }
    else
    {
        const int code = errno;
        printf( "mq_open failed, code %i, message %s\n", code, strerror( code ) );
        return -1;
    }
}

但是,当从 C++ 控制台应用程序调用相同的 DLL 时,它运行良好并打印“mq_open completed OK”:

// gcc load.cpp -ldl && ./a.out
#include <dlfcn.h>
#include <stdio.h>

using pfnTest = int( * )( );
int main()
{
    void * const handle = dlopen( "./libNativeHelpers.so", RTLD_NOW );
    if( nullptr == handle )
    {
        printf( "dlopen failed: %s\n", dlerror() );
        return 1;
    }

    const pfnTest pfn = (pfnTest)dlsym( handle, "mq_test" );
    if( nullptr == pfn )
    {
        printf( "dlsym failed: %s\n", dlerror() );
        return 2;
    }
    return pfn();
}

我在同一个用户帐户下运行这两个程序,但 C++ 程序具有所有必需的权限,而 C# 程序没有。任何想法如何找出发生了什么?

操作系统为 Ubuntu 20.04.3 LTS,架构为 AMD64,.NET 为 5.0.9。

【问题讨论】:

  • 关于你的标签:问题基本上是“环境”——不是“C++”,不是“Linux”。问:操作系统真的是“ubuntu 20.04.3.LTS”(独立安装)......还是WSL下的Ubuntu?问:你们的 MQ 实施究竟是什么? OOTB Posix message queues,或“其他”(例如 Rabbit MQ)?
  • @paulsm4 “不是“C++”,不是“Linux”” 在我找到答案之前我应该​​怎么知道? “操作系统真的吗”是的,尽管硬件是假的,但我正在使用 VMWare Workstation 16.1.2 来运行那个 Ubuntu。不确定我是否理解最后一个问题,那是一个 Linux 内核 API:man7.org/linux/man-pages/man3/mq_open.3.html

标签: c++ linux ubuntu .net-core .net-5


【解决方案1】:

它是snap。微软做出了一个有趣的选择,将他们的 .NET 框架(专为软件开发人员设计)在一个沙箱中发布,该沙箱将实际操作系统隐藏在抽象背后。

在底层,那个东西正在使用AppArmor 内核模块。这就是产生拒绝访问状态的原因。同样,有趣的选择,IMO SELinux 通常更适合此类事情。

一旦我卸载了 .NET runtine 的 snap 包,并使用 apt-get 安装了本机版本,我的代码就开始正常工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-28
    • 2012-04-10
    • 2012-11-05
    • 2020-10-26
    • 2021-09-14
    • 1970-01-01
    • 2018-03-27
    相关资源
    最近更新 更多