@@ -466,7 +466,8 @@ static int pid_notify_with_fds_internal(
466
466
struct cmsghdr * cmsg = NULL ;
467
467
const char * e ;
468
468
bool send_ucred ;
469
- int r ;
469
+ ssize_t n ;
470
+ int type , r ;
470
471
471
472
if (!state )
472
473
return - EINVAL ;
@@ -491,30 +492,37 @@ static int pid_notify_with_fds_internal(
491
492
if (address .sockaddr .vm .svm_family == AF_VSOCK && address .sockaddr .vm .svm_cid == VMADDR_CID_ANY )
492
493
return - EINVAL ;
493
494
495
+ type = address .type == 0 ? SOCK_DGRAM : address .type ;
496
+
494
497
/* At the time of writing QEMU does not yet support AF_VSOCK + SOCK_DGRAM and returns
495
498
* ENODEV. Fallback to SOCK_SEQPACKET in that case. */
496
- fd = socket (address .sockaddr .sa .sa_family , SOCK_DGRAM |SOCK_CLOEXEC , 0 );
499
+ fd = socket (address .sockaddr .sa .sa_family , type |SOCK_CLOEXEC , 0 );
497
500
if (fd < 0 ) {
498
- if (!(ERRNO_IS_NOT_SUPPORTED (errno ) || errno == ENODEV ) || address .sockaddr .sa .sa_family != AF_VSOCK )
499
- return log_debug_errno (errno , "Failed to open datagram notify socket to '%s': %m" , e );
500
-
501
- fd = socket (address .sockaddr .sa .sa_family , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 );
501
+ if (!(ERRNO_IS_NOT_SUPPORTED (errno ) || errno == ENODEV ) || address .sockaddr .sa .sa_family != AF_VSOCK || address .type > 0 )
502
+ return log_debug_errno (errno , "Failed to open %s notify socket to '%s': %m" , socket_address_type_to_string (type ), e );
503
+
504
+ type = SOCK_SEQPACKET ;
505
+ fd = socket (address .sockaddr .sa .sa_family , type |SOCK_CLOEXEC , 0 );
506
+ if (fd < 0 && ERRNO_IS_NOT_SUPPORTED (errno )) {
507
+ type = SOCK_STREAM ;
508
+ fd = socket (address .sockaddr .sa .sa_family , type |SOCK_CLOEXEC , 0 );
509
+ }
502
510
if (fd < 0 )
503
- return log_debug_errno (errno , "Failed to open sequential packet socket to '%s': %m" , e );
511
+ return log_debug_errno (errno , "Failed to open %s socket to '%s': %m" , socket_address_type_to_string (type ), e );
512
+ }
504
513
514
+ if (address .sockaddr .sa .sa_family == AF_VSOCK ) {
505
515
r = vsock_bind_privileged_port (fd );
506
516
if (r < 0 && !ERRNO_IS_PRIVILEGE (r ))
507
517
return log_debug_errno (r , "Failed to bind socket to privileged port: %m" );
518
+ }
508
519
520
+ if (IN_SET (type , SOCK_STREAM , SOCK_SEQPACKET )) {
509
521
if (connect (fd , & address .sockaddr .sa , address .size ) < 0 )
510
522
return log_debug_errno (errno , "Failed to connect socket to '%s': %m" , e );
511
523
512
524
msghdr .msg_name = NULL ;
513
525
msghdr .msg_namelen = 0 ;
514
- } else if (address .sockaddr .sa .sa_family == AF_VSOCK ) {
515
- r = vsock_bind_privileged_port (fd );
516
- if (r < 0 && !ERRNO_IS_PRIVILEGE (r ))
517
- return log_debug_errno (r , "Failed to bind socket to privileged port: %m" );
518
526
}
519
527
520
528
(void ) fd_inc_sndbuf (fd , SNDBUF_SIZE );
@@ -560,21 +568,32 @@ static int pid_notify_with_fds_internal(
560
568
}
561
569
}
562
570
563
- /* First try with fake ucred data, as requested */
564
- if (sendmsg (fd , & msghdr , MSG_NOSIGNAL ) >= 0 )
565
- return 1 ;
566
-
567
- /* If that failed, try with our own ucred instead */
568
- if (send_ucred ) {
569
- msghdr .msg_controllen -= CMSG_SPACE (sizeof (struct ucred ));
570
- if (msghdr .msg_controllen == 0 )
571
+ do {
572
+ /* First try with fake ucred data, as requested */
573
+ n = sendmsg (fd , & msghdr , MSG_NOSIGNAL );
574
+ if (n < 0 ) {
575
+ if (!send_ucred )
576
+ return log_debug_errno (errno , "Failed to send notify message to '%s': %m" , e );
577
+
578
+ /* If that failed, try with our own ucred instead */
579
+ msghdr .msg_controllen -= CMSG_SPACE (sizeof (struct ucred ));
580
+ if (msghdr .msg_controllen == 0 )
581
+ msghdr .msg_control = NULL ;
582
+
583
+ n = 0 ;
584
+ send_ucred = false;
585
+ } else {
586
+ /* Unless we're using SOCK_STREAM, we expect to write all the contents immediately. */
587
+ if (type != SOCK_STREAM && (size_t ) n < IOVEC_TOTAL_SIZE (msghdr .msg_iov , msghdr .msg_iovlen ))
588
+ return - EIO ;
589
+
590
+ /* Make sure we only send fds and ucred once, even if we're using SOCK_STREAM. */
571
591
msghdr .msg_control = NULL ;
592
+ msghdr .msg_controllen = 0 ;
593
+ }
594
+ } while (!IOVEC_INCREMENT (msghdr .msg_iov , msghdr .msg_iovlen , n ));
572
595
573
- if (sendmsg (fd , & msghdr , MSG_NOSIGNAL ) >= 0 )
574
- return 1 ;
575
- }
576
-
577
- return log_debug_errno (errno , "Failed to send notify message to '%s': %m" , e );
596
+ return 1 ;
578
597
}
579
598
580
599
_public_ int sd_pid_notify_with_fds (
0 commit comments