我有一种情况,我打算通过文件系统上的UNIX域套接字提供的命令接口与服务进行通信。我能够成功发送命令,但有一段时间我感到困惑,为什么我无法接收任何对我的查询的响应。
事实证明,该服务没有足够的权限来写入为其提供的地址I(或OS)。但是,我意识到如果我明确bind
到文件系统上的地址,那么我可以通过利用chmod
来调整文件权限。
类似的东西:
int mySocket;
struct sockaddr_un local_addr;
mySocket = socket(AF_UNIX, SOCK_DGRAM, 0);
local_addr.sun_family = AF_UNIX;
snprintf(local_addr.sun_path, 108 "/path/to/mySocket");
bind(mySocket, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_un));
chmod("/path/to/mySocket", 777);
也就是说,如果没有最后的chmod
步骤,该服务将无法写入mySocket
,因为它没有相应的写入权限。显然,如果没有明确地bind
到特定地址,这是一个更难发现的问题,因为底层操作系统将隐式为用户生成此套接字 - 但它仍然存在且仍然将有相同的访问问题。
那么,我的问题就是最后一步。有没有办法允许操作系统隐式生成我的端点的套接字(即服务将响应的地址),但是请求给它一定的权限?
解释
此问题成为问题的原因是由于要求程序的其他部分以root身份执行。因此,当我作为root用户尝试connect
/ send
到后台服务时,操作系统将隐式创建一个回复将被定向到的地址。但是,这会导致我的套接字文件无论是隐式的还是使用bind
创建的,都具有srw- --- ---
等权限,因此另一个端点只有在它们自身提升时才会回复。< / p>
因此,如果我首先bind
然后chmod
权限,问题就会消失,如上所示。
答案 0 :(得分:3)
有没有办法允许操作系统隐式生成我的端点的套接字(即服务将响应的地址),但是请求给它一定的权限?
我使用两次umask()
调用解决了这个问题。
伪代码:
current_mask = umask(umask_to_be_used_on_afunix_socket_file_system_entry_creation);
bind afunix socket here
umask(current_umask);
答案 1 :(得分:-1)
[编辑]我的第一个猜测是改为使用fifo,它允许你先创建文件并设置其权限。此外,如果两个用户要通过fifo进行通信,最好使用组级读/写并将它们放在同一组中。
$ mkfifo -m 660 fifo_name
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
正如sherrellbc所提到的,这与unix套接字无关。如果您被迫使用套接字,为什么不在创建它之前删除权限?无论如何,这似乎是运行suid时的一个重要步骤。
struct sockaddr_un to_addr;
memset(&to_addr, 0, sizeof(struct sockaddr_un));
strncpy(to_addr.sun_path, "/path/to/socket", sizeof(to_addr.sun_path) - 1);
to_addr.sun_family = AF_UNIX;
/* ------------ change user ------------ */
if(setgid(new_gid) || setuid(new_uid))
goto error;
handle_conn(&to_addr, sizeof(struct sockaddr_un));
int handle_conn(struct sockaddr *to_addr, socklen_t addrlen) {
int to_sock;
int ret;
pid_t pid;
if( (to_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error;
}
if(connect(to_sock, to_addr, addrlen)) {
close(to_sock);
goto error;
}
...
close(to_sock);
}