从.NET调用C++ DLL创建消息队列报access denied错误如何解决?
问题排查步骤
- 第一步:验证AppArmor策略限制(Ubuntu 20.04默认对dotnet进程有默认限制规则,是该问题的最高概率诱因)
- 执行命令
sudo aa-status,查看输出中是否存在/usr/bin/dotnet处于enforce强制模式的条目 - 临时将dotnet的AppArmor策略切换为投诉模式:
sudo aa-complain /usr/bin/dotnet - 重新运行.NET程序,如果此时
mq_open运行成功,则可确认问题根源为AppArmor的权限限制
- 执行命令
- 第二步:校验进程实际权限一致性
在mq_test函数中增加日志打印当前进程的有效用户ID和有效用户组ID:
分别从C++控制台和.NET调用该函数,对比两次输出的ID是否完全一致,排除进程权限被篡改的可能printf("euid: %d, egid: %d\n", geteuid(), getegid()); - 第三步:验证POSIX消息队列内核参数
执行命令cat /proc/sys/fs/mqueue/msg_max,确认输出值不小于代码中设置的mq_maxmsg=10,该参数默认值为10,C++程序能正常运行的情况下该参数异常概率极低。
解决方案
如果确认是AppArmor策略限制导致的问题,按以下步骤修改规则即可:
- 找到dotnet对应的AppArmor配置文件:
- 若为apt安装的dotnet,路径为
/etc/apparmor.d/usr.bin.dotnet - 若为snap安装的dotnet,路径为
/var/lib/snapd/apparmor/profiles/snap.dotnet.dotnet
- 若为apt安装的dotnet,路径为
- 编辑配置文件,在规则块中添加以下两条权限规则:
owner /dev/mqueue/* rw, capability sys_resource, - 重新加载AppArmor规则使其生效:
sudo apparmor_parser -r /path/to/your/dotnet/apparmor/profile - 恢复dotnet的AppArmor强制模式:
sudo aa-enforce /usr/bin/dotnet,再运行.NET程序即可正常调用mq_open。
如果是snap安装的dotnet,也可以直接卸载snap版本,改用官方apt源或者手动二进制安装的dotnet版本,默认不会有额外的AppArmor沙箱限制。
内容的提问来源于stack exchange,提问作者Soonts
相关产品推荐
相关产品推荐

