Skip to content

Commit 5cde609

Browse files
committed
um: generalize os_rcv_fd
Change os_rcv_fd() to os_rcv_fd_msg() that can more generally receive any number of FDs in any kind of message. Link: https://patch.msgid.link/20240702192118.40b78b2bfe4e.Ic6ec12d72630e5bcae1e597d6bd5c6f29f441563@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 6555acd commit 5cde609

File tree

6 files changed

+54
-41
lines changed

6 files changed

+54
-41
lines changed

arch/um/drivers/port_kern.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@ struct connection {
4545
static irqreturn_t pipe_interrupt(int irq, void *data)
4646
{
4747
struct connection *conn = data;
48-
int fd;
48+
int n_fds = 1, fd = -1;
49+
ssize_t ret;
4950

50-
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
51-
if (fd < 0) {
52-
if (fd == -EAGAIN)
51+
ret = os_rcv_fd_msg(conn->socket[0], &fd, n_fds, &conn->helper_pid,
52+
sizeof(conn->helper_pid));
53+
if (ret != sizeof(conn->helper_pid)) {
54+
if (ret == -EAGAIN)
5355
return IRQ_NONE;
5456

55-
printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
56-
-fd);
57+
printk(KERN_ERR "pipe_interrupt : os_rcv_fd_msg returned %zd\n",
58+
ret);
5759
os_close_file(conn->fd);
5860
}
5961

arch/um/drivers/xterm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static int xterm_open(int input, int output, int primary, void *d,
156156
new = xterm_fd(fd, &data->helper_pid);
157157
if (new < 0) {
158158
err = new;
159-
printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
159+
printk(UM_KERN_ERR "xterm_open : xterm_fd failed, err = %d\n",
160160
-err);
161161
goto out_kill;
162162
}

arch/um/drivers/xterm_kern.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@ struct xterm_wait {
2121
static irqreturn_t xterm_interrupt(int irq, void *data)
2222
{
2323
struct xterm_wait *xterm = data;
24-
int fd;
24+
int fd = -1, n_fds = 1;
25+
ssize_t ret;
2526

26-
fd = os_rcv_fd(xterm->fd, &xterm->pid);
27-
if (fd == -EAGAIN)
27+
ret = os_rcv_fd_msg(xterm->fd, &fd, n_fds,
28+
&xterm->pid, sizeof(xterm->pid));
29+
if (ret == -EAGAIN)
2830
return IRQ_NONE;
2931

32+
if (ret < 0)
33+
fd = ret;
34+
else if (ret != sizeof(xterm->pid))
35+
fd = -EMSGSIZE;
36+
3037
xterm->new_fd = fd;
3138
complete(&xterm->ready);
3239

arch/um/include/shared/os.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
165165
extern int os_shutdown_socket(int fd, int r, int w);
166166
extern int os_dup_file(int fd);
167167
extern void os_close_file(int fd);
168-
extern int os_rcv_fd(int fd, int *helper_pid_out);
168+
ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
169+
void *data, size_t data_len);
169170
extern int os_connect_socket(const char *name);
170171
extern int os_file_type(char *file);
171172
extern int os_file_mode(const char *file, struct openflags *mode_out);

arch/um/kernel/ksyms.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ EXPORT_SYMBOL(os_shutdown_socket);
3333
EXPORT_SYMBOL(os_create_unix_socket);
3434
EXPORT_SYMBOL(os_connect_socket);
3535
EXPORT_SYMBOL(os_accept_connection);
36-
EXPORT_SYMBOL(os_rcv_fd);
36+
EXPORT_SYMBOL(os_rcv_fd_msg);
3737
EXPORT_SYMBOL(run_helper);
3838
EXPORT_SYMBOL(os_major);
3939
EXPORT_SYMBOL(os_minor);

arch/um/os-Linux/file.c

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -512,44 +512,47 @@ int os_shutdown_socket(int fd, int r, int w)
512512
return 0;
513513
}
514514

515-
int os_rcv_fd(int fd, int *helper_pid_out)
515+
/**
516+
* os_rcv_fd_msg - receive message with (optional) FDs
517+
* @fd: the FD to receive from
518+
* @fds: the array for FDs to write to
519+
* @n_fds: number of FDs to receive (@fds array size)
520+
* @data: the message buffer
521+
* @data_len: the size of the message to receive
522+
*
523+
* Receive a message with FDs.
524+
*
525+
* Returns: the size of the received message, or an error code
526+
*/
527+
ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
528+
void *data, size_t data_len)
516529
{
517-
int new, n;
518-
char buf[CMSG_SPACE(sizeof(new))];
519-
struct msghdr msg;
530+
char buf[CMSG_SPACE(sizeof(*fds) * n_fds)];
520531
struct cmsghdr *cmsg;
521-
struct iovec iov;
522-
523-
msg.msg_name = NULL;
524-
msg.msg_namelen = 0;
525-
iov = ((struct iovec) { .iov_base = helper_pid_out,
526-
.iov_len = sizeof(*helper_pid_out) });
527-
msg.msg_iov = &iov;
528-
msg.msg_iovlen = 1;
529-
msg.msg_control = buf;
530-
msg.msg_controllen = sizeof(buf);
531-
msg.msg_flags = 0;
532+
struct iovec iov = {
533+
.iov_base = data,
534+
.iov_len = data_len,
535+
};
536+
struct msghdr msg = {
537+
.msg_iov = &iov,
538+
.msg_iovlen = 1,
539+
.msg_control = buf,
540+
.msg_controllen = sizeof(buf),
541+
};
542+
int n;
532543

533544
n = recvmsg(fd, &msg, 0);
534545
if (n < 0)
535546
return -errno;
536-
else if (n != iov.iov_len)
537-
*helper_pid_out = -1;
538547

539548
cmsg = CMSG_FIRSTHDR(&msg);
540-
if (cmsg == NULL) {
541-
printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
542-
"error = %d\n", errno);
543-
return -1;
544-
}
545-
if ((cmsg->cmsg_level != SOL_SOCKET) ||
546-
(cmsg->cmsg_type != SCM_RIGHTS)) {
547-
printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
548-
return -1;
549-
}
549+
if (!cmsg ||
550+
cmsg->cmsg_level != SOL_SOCKET ||
551+
cmsg->cmsg_type != SCM_RIGHTS)
552+
return n;
550553

551-
new = ((int *) CMSG_DATA(cmsg))[0];
552-
return new;
554+
memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len);
555+
return n;
553556
}
554557

555558
int os_create_unix_socket(const char *file, int len, int close_on_exec)

0 commit comments

Comments
 (0)