socket() 设置的 Errno 在联机帮助页中未记录
Errno set by socket() is undocumented in the manpage
本文档 socket(3p)
documents the signature to this function and a basic introduction on how to use it. The error section 的联机帮助页列出了几个 errno
值,并解释了错误发生的原因。不幸的是,我在读取 EPERM
时收到一个未记录的错误,其中数字 1
表示 Operation not permitted
。未记录的 errno
最初是在 glibc-2.33
和 clang-12.0.1
的 ArchLinux 环境下发现的。我希望以下概念验证 (PoC) 可以在其他 Linux 环境中重现:
#include <errno.h>
#include <sys/socket.h>
#include <netinet/ip.h>
int main() {
socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
return errno;
}
以下命令可能有助于重现,其中 PoC 代码存储在文件 raw-socket-poc.c
:
$ clang -O0 -g raw-socket-poc.c -o raw-socket-poc
$ ./raw-socket-poc; errno $?
EPERM 1 Operation not permitted
其他观察表明,将 IPPROTO_TCP
更改为 IPPROTO_UDP
没有任何帮助。但是,通过将 IPROTO_TCP
替换为建议的 0
,程序以记录错误 EPROTONOSUPPORT 93 Protocol not supported
结束。进一步的实验注意到 运行 作为 root 的原始 PoC yold 没有错误。不幸的是,如果 PoC 运行 作为具有 CAP_NET_RAW
能力的非特权用户,就会发生未记录的错误。与 # setcap CAP_NET_RAW=+eip ./raw-socket-poc
关联的 PoC 的能力提升,并用 $ getcap ./raw-socket-poc
进行了双重检查,其中 ./raw-socket-poc cap_net_raw=eip
显示。
由于信息有限,很难得出缺少文档是故意为之还是设计使然的结论。因此,如果有关于如何使用联机帮助页和原始套接字相关功能的解释,我们将不胜感激。
如果您查看“错误”部分底部的 man 2 socket
。你会看到它提到可能会产生其他错误。
ERRORS
EACCES Permission to create a socket of the specified type and/or pro‐
tocol is denied.
EAFNOSUPPORT
The implementation does not support the specified address fam‐
ily.
EINVAL Unknown protocol, or protocol family not available.
EINVAL Invalid flags in type.
EMFILE Process file table overflow.
ENFILE The system limit on the total number of open files has been
reached.
ENOBUFS or ENOMEM
Insufficient memory is available. The socket cannot be created
until sufficient resources are freed.
EPROTONOSUPPORT
The protocol type or the specified protocol is not supported
within this domain.
Other errors may be generated by the underlying protocol modules.
如果我们再检查 man 7 raw
:
SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(AF_INET, SOCK_RAW, int protocol);
...
ERRORS
EACCES User tried to send to a broadcast address without having
the broadcast flag set on the socket.
EFAULT An invalid memory address was supplied.
EINVAL Invalid argument.
EMSGSIZE
Packet too big. Either Path MTU Discovery is enabled (the
IP_MTU_DISCOVER socket flag) or the packet size exceeds
the maximum allowed IPv4 packet size of 64 kB.
EOPNOTSUPP
Invalid flag has been passed to a socket call (like
MSG_OOB).
EPERM The user doesn't have permission to open raw sockets.
Only processes with an effective user ID of 0 or the
CAP_NET_RAW attribute may do that.
EPROTO An ICMP error has arrived reporting a parameter problem.
我们看到可以生成EPERM
本文档 socket(3p)
documents the signature to this function and a basic introduction on how to use it. The error section 的联机帮助页列出了几个 errno
值,并解释了错误发生的原因。不幸的是,我在读取 EPERM
时收到一个未记录的错误,其中数字 1
表示 Operation not permitted
。未记录的 errno
最初是在 glibc-2.33
和 clang-12.0.1
的 ArchLinux 环境下发现的。我希望以下概念验证 (PoC) 可以在其他 Linux 环境中重现:
#include <errno.h>
#include <sys/socket.h>
#include <netinet/ip.h>
int main() {
socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
return errno;
}
以下命令可能有助于重现,其中 PoC 代码存储在文件 raw-socket-poc.c
:
$ clang -O0 -g raw-socket-poc.c -o raw-socket-poc
$ ./raw-socket-poc; errno $?
EPERM 1 Operation not permitted
其他观察表明,将 IPPROTO_TCP
更改为 IPPROTO_UDP
没有任何帮助。但是,通过将 IPROTO_TCP
替换为建议的 0
,程序以记录错误 EPROTONOSUPPORT 93 Protocol not supported
结束。进一步的实验注意到 运行 作为 root 的原始 PoC yold 没有错误。不幸的是,如果 PoC 运行 作为具有 CAP_NET_RAW
能力的非特权用户,就会发生未记录的错误。与 # setcap CAP_NET_RAW=+eip ./raw-socket-poc
关联的 PoC 的能力提升,并用 $ getcap ./raw-socket-poc
进行了双重检查,其中 ./raw-socket-poc cap_net_raw=eip
显示。
由于信息有限,很难得出缺少文档是故意为之还是设计使然的结论。因此,如果有关于如何使用联机帮助页和原始套接字相关功能的解释,我们将不胜感激。
如果您查看“错误”部分底部的 man 2 socket
。你会看到它提到可能会产生其他错误。
ERRORS
EACCES Permission to create a socket of the specified type and/or pro‐
tocol is denied.
EAFNOSUPPORT
The implementation does not support the specified address fam‐
ily.
EINVAL Unknown protocol, or protocol family not available.
EINVAL Invalid flags in type.
EMFILE Process file table overflow.
ENFILE The system limit on the total number of open files has been
reached.
ENOBUFS or ENOMEM
Insufficient memory is available. The socket cannot be created
until sufficient resources are freed.
EPROTONOSUPPORT
The protocol type or the specified protocol is not supported
within this domain.
Other errors may be generated by the underlying protocol modules.
如果我们再检查 man 7 raw
:
SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(AF_INET, SOCK_RAW, int protocol);
...
ERRORS
EACCES User tried to send to a broadcast address without having
the broadcast flag set on the socket.
EFAULT An invalid memory address was supplied.
EINVAL Invalid argument.
EMSGSIZE
Packet too big. Either Path MTU Discovery is enabled (the
IP_MTU_DISCOVER socket flag) or the packet size exceeds
the maximum allowed IPv4 packet size of 64 kB.
EOPNOTSUPP
Invalid flag has been passed to a socket call (like
MSG_OOB).
EPERM The user doesn't have permission to open raw sockets.
Only processes with an effective user ID of 0 or the
CAP_NET_RAW attribute may do that.
EPROTO An ICMP error has arrived reporting a parameter problem.
我们看到可以生成EPERM