Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: mctp: Allow limiting binds to a peer address

Prior to calling bind() a program may call connect() on a socket to
restrict to a remote peer address.

Using connect() is the normal mechanism to specify a remote network
peer, so we use that here. In MCTP connect() is only used for bound
sockets - send() is not available for MCTP since a tag must be provided
for each message.

The smctp_type must match between connect() and bind() calls.

Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
Link: https://patch.msgid.link/20250710-mctp-bind-v4-6-8ec2f6460c56@codeconstruct.com.au
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Matt Johnston and committed by
Paolo Abeni
3549eb08 1aeed732

+108 -8
+4 -1
include/net/mctp.h
··· 69 69 70 70 /* bind() params */ 71 71 unsigned int bind_net; 72 - mctp_eid_t bind_addr; 72 + mctp_eid_t bind_local_addr; 73 + mctp_eid_t bind_peer_addr; 74 + unsigned int bind_peer_net; 75 + bool bind_peer_set; 73 76 __u8 bind_type; 74 77 75 78 /* sendmsg()/recvmsg() uses struct sockaddr_mctp_ext */
+99 -6
net/mctp/af_mctp.c
··· 79 79 goto out_release; 80 80 } 81 81 82 - msk->bind_addr = smctp->smctp_addr.s_addr; 82 + msk->bind_local_addr = smctp->smctp_addr.s_addr; 83 83 84 84 /* MCTP_NET_ANY with a specific EID is resolved to the default net 85 85 * at bind() time. ··· 87 87 * lookup time. 88 88 */ 89 89 if (smctp->smctp_network == MCTP_NET_ANY && 90 - msk->bind_addr != MCTP_ADDR_ANY) { 90 + msk->bind_local_addr != MCTP_ADDR_ANY) { 91 91 msk->bind_net = mctp_default_net(net); 92 92 } else { 93 93 msk->bind_net = smctp->smctp_network; 94 94 } 95 95 96 - msk->bind_type = smctp->smctp_type & 0x7f; /* ignore the IC bit */ 96 + /* ignore the IC bit */ 97 + smctp->smctp_type &= 0x7f; 98 + 99 + if (msk->bind_peer_set) { 100 + if (msk->bind_type != smctp->smctp_type) { 101 + /* Prior connect() had a different type */ 102 + rc = -EINVAL; 103 + goto out_release; 104 + } 105 + 106 + if (msk->bind_net == MCTP_NET_ANY) { 107 + /* Restrict to the network passed to connect() */ 108 + msk->bind_net = msk->bind_peer_net; 109 + } 110 + 111 + if (msk->bind_net != msk->bind_peer_net) { 112 + /* connect() had a different net to bind() */ 113 + rc = -EINVAL; 114 + goto out_release; 115 + } 116 + } else { 117 + msk->bind_type = smctp->smctp_type; 118 + } 97 119 98 120 rc = sk->sk_prot->hash(sk); 99 121 100 122 out_release: 101 123 release_sock(sk); 102 124 125 + return rc; 126 + } 127 + 128 + /* Used to set a specific peer prior to bind. Not used for outbound 129 + * connections (Tag Owner set) since MCTP is a datagram protocol. 130 + */ 131 + static int mctp_connect(struct socket *sock, struct sockaddr *addr, 132 + int addrlen, int flags) 133 + { 134 + struct sock *sk = sock->sk; 135 + struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 136 + struct net *net = sock_net(&msk->sk); 137 + struct sockaddr_mctp *smctp; 138 + int rc; 139 + 140 + if (addrlen != sizeof(*smctp)) 141 + return -EINVAL; 142 + 143 + if (addr->sa_family != AF_MCTP) 144 + return -EAFNOSUPPORT; 145 + 146 + /* It's a valid sockaddr for MCTP, cast and do protocol checks */ 147 + smctp = (struct sockaddr_mctp *)addr; 148 + 149 + if (!mctp_sockaddr_is_ok(smctp)) 150 + return -EINVAL; 151 + 152 + /* Can't bind by tag */ 153 + if (smctp->smctp_tag) 154 + return -EINVAL; 155 + 156 + /* IC bit must be unset */ 157 + if (smctp->smctp_type & 0x80) 158 + return -EINVAL; 159 + 160 + lock_sock(sk); 161 + 162 + if (sk_hashed(sk)) { 163 + /* bind() already */ 164 + rc = -EADDRINUSE; 165 + goto out_release; 166 + } 167 + 168 + if (msk->bind_peer_set) { 169 + /* connect() already */ 170 + rc = -EADDRINUSE; 171 + goto out_release; 172 + } 173 + 174 + msk->bind_peer_set = true; 175 + msk->bind_peer_addr = smctp->smctp_addr.s_addr; 176 + msk->bind_type = smctp->smctp_type; 177 + if (smctp->smctp_network == MCTP_NET_ANY) 178 + msk->bind_peer_net = mctp_default_net(net); 179 + else 180 + msk->bind_peer_net = smctp->smctp_network; 181 + 182 + rc = 0; 183 + 184 + out_release: 185 + release_sock(sk); 103 186 return rc; 104 187 } 105 188 ··· 629 546 .family = PF_MCTP, 630 547 .release = mctp_release, 631 548 .bind = mctp_bind, 632 - .connect = sock_no_connect, 549 + .connect = mctp_connect, 633 550 .socketpair = sock_no_socketpair, 634 551 .accept = sock_no_accept, 635 552 .getname = sock_no_getname, ··· 696 613 697 614 INIT_HLIST_HEAD(&msk->keys); 698 615 timer_setup(&msk->key_expiry, mctp_sk_expire_keys, 0); 616 + msk->bind_peer_set = false; 699 617 return 0; 700 618 } 701 619 ··· 710 626 struct net *net = sock_net(sk); 711 627 struct sock *existing; 712 628 struct mctp_sock *msk; 629 + mctp_eid_t remote; 713 630 u32 hash; 714 631 int rc; 715 632 716 633 msk = container_of(sk, struct mctp_sock, sk); 717 634 718 - hash = mctp_bind_hash(msk->bind_type, msk->bind_addr, MCTP_ADDR_ANY); 635 + if (msk->bind_peer_set) 636 + remote = msk->bind_peer_addr; 637 + else 638 + remote = MCTP_ADDR_ANY; 639 + hash = mctp_bind_hash(msk->bind_type, msk->bind_local_addr, remote); 719 640 720 641 mutex_lock(&net->mctp.bind_lock); 721 642 ··· 729 640 struct mctp_sock *mex = 730 641 container_of(existing, struct mctp_sock, sk); 731 642 643 + bool same_peer = (mex->bind_peer_set && msk->bind_peer_set && 644 + mex->bind_peer_addr == msk->bind_peer_addr) || 645 + (!mex->bind_peer_set && !msk->bind_peer_set); 646 + 732 647 if (mex->bind_type == msk->bind_type && 733 - mex->bind_addr == msk->bind_addr && 648 + mex->bind_local_addr == msk->bind_local_addr && same_peer && 734 649 mex->bind_net == msk->bind_net) { 735 650 rc = -EADDRINUSE; 736 651 goto out;
+5 -1
net/mctp/route.c
··· 65 65 if (msk->bind_type != type) 66 66 continue; 67 67 68 - if (!mctp_address_matches(msk->bind_addr, dest)) 68 + if (msk->bind_peer_set && 69 + !mctp_address_matches(msk->bind_peer_addr, src)) 70 + continue; 71 + 72 + if (!mctp_address_matches(msk->bind_local_addr, dest)) 69 73 continue; 70 74 71 75 return msk;