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.

Revert "net/smc: Introduce TCP ULP support"

This reverts commit d7cd421da9da2cc7b4d25b8537f66db5c8331c40.

As reported by Al Viro, the TCP ULP support for SMC is fundamentally
broken. The implementation attempts to convert an active TCP socket
into an SMC socket by modifying the underlying `struct file`, dentry,
and inode in-place, which violates core VFS invariants that assume
these structures are immutable for an open file, creating a risk of
use after free errors and general system instability.

Given the severity of this design flaw and the fact that cleaner
alternatives (e.g., LD_PRELOAD, BPF) exist for legacy application
transparency, the correct course of action is to remove this feature
entirely.

Fixes: d7cd421da9da ("net/smc: Introduce TCP ULP support")
Link: https://lore.kernel.org/netdev/Yus1SycZxcd+wHwz@ZenIV/
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: Tony Lu <tonylu@linux.alibaba.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260128055452.98251-1-alibuda@linux.alibaba.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

D. Wythe and committed by
Jakub Kicinski
df31a6b0 82fff3b0

+4 -87
+4 -87
net/smc/af_smc.c
··· 3357 3357 return 0; 3358 3358 } 3359 3359 3360 - static int __smc_create(struct net *net, struct socket *sock, int protocol, 3361 - int kern, struct socket *clcsock) 3360 + static int smc_create(struct net *net, struct socket *sock, int protocol, 3361 + int kern) 3362 3362 { 3363 3363 int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET; 3364 - struct smc_sock *smc; 3365 3364 struct sock *sk; 3366 3365 int rc; 3367 3366 ··· 3379 3380 if (!sk) 3380 3381 goto out; 3381 3382 3382 - /* create internal TCP socket for CLC handshake and fallback */ 3383 - smc = smc_sk(sk); 3384 - 3385 - rc = 0; 3386 - if (clcsock) 3387 - smc->clcsock = clcsock; 3388 - else 3389 - rc = smc_create_clcsk(net, sk, family); 3390 - 3383 + rc = smc_create_clcsk(net, sk, family); 3391 3384 if (rc) { 3392 3385 sk_common_release(sk); 3393 3386 sock->sk = NULL; ··· 3388 3397 return rc; 3389 3398 } 3390 3399 3391 - static int smc_create(struct net *net, struct socket *sock, int protocol, 3392 - int kern) 3393 - { 3394 - return __smc_create(net, sock, protocol, kern, NULL); 3395 - } 3396 - 3397 3400 static const struct net_proto_family smc_sock_family_ops = { 3398 3401 .family = PF_SMC, 3399 3402 .owner = THIS_MODULE, 3400 3403 .create = smc_create, 3401 - }; 3402 - 3403 - static int smc_ulp_init(struct sock *sk) 3404 - { 3405 - struct socket *tcp = sk->sk_socket; 3406 - struct net *net = sock_net(sk); 3407 - struct socket *smcsock; 3408 - int protocol, ret; 3409 - 3410 - /* only TCP can be replaced */ 3411 - if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP || 3412 - (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)) 3413 - return -ESOCKTNOSUPPORT; 3414 - /* don't handle wq now */ 3415 - if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list) 3416 - return -ENOTCONN; 3417 - 3418 - if (sk->sk_family == AF_INET) 3419 - protocol = SMCPROTO_SMC; 3420 - else 3421 - protocol = SMCPROTO_SMC6; 3422 - 3423 - smcsock = sock_alloc(); 3424 - if (!smcsock) 3425 - return -ENFILE; 3426 - 3427 - smcsock->type = SOCK_STREAM; 3428 - __module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */ 3429 - ret = __smc_create(net, smcsock, protocol, 1, tcp); 3430 - if (ret) { 3431 - sock_release(smcsock); /* module_put() which ops won't be NULL */ 3432 - return ret; 3433 - } 3434 - 3435 - /* replace tcp socket to smc */ 3436 - smcsock->file = tcp->file; 3437 - smcsock->file->private_data = smcsock; 3438 - smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */ 3439 - smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */ 3440 - tcp->file = NULL; 3441 - 3442 - return ret; 3443 - } 3444 - 3445 - static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk, 3446 - const gfp_t priority) 3447 - { 3448 - struct inet_connection_sock *icsk = inet_csk(newsk); 3449 - 3450 - /* don't inherit ulp ops to child when listen */ 3451 - icsk->icsk_ulp_ops = NULL; 3452 - } 3453 - 3454 - static struct tcp_ulp_ops smc_ulp_ops __read_mostly = { 3455 - .name = "smc", 3456 - .owner = THIS_MODULE, 3457 - .init = smc_ulp_init, 3458 - .clone = smc_ulp_clone, 3459 3404 }; 3460 3405 3461 3406 unsigned int smc_net_id; ··· 3516 3589 pr_err("%s: ib_register fails with %d\n", __func__, rc); 3517 3590 goto out_sock; 3518 3591 } 3519 - 3520 - rc = tcp_register_ulp(&smc_ulp_ops); 3521 - if (rc) { 3522 - pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc); 3523 - goto out_ib; 3524 - } 3525 3592 rc = smc_inet_init(); 3526 3593 if (rc) { 3527 3594 pr_err("%s: smc_inet_init fails with %d\n", __func__, rc); 3528 - goto out_ulp; 3595 + goto out_ib; 3529 3596 } 3530 3597 rc = bpf_smc_hs_ctrl_init(); 3531 3598 if (rc) { ··· 3531 3610 return 0; 3532 3611 out_inet: 3533 3612 smc_inet_exit(); 3534 - out_ulp: 3535 - tcp_unregister_ulp(&smc_ulp_ops); 3536 3613 out_ib: 3537 3614 smc_ib_unregister_client(); 3538 3615 out_sock: ··· 3566 3647 { 3567 3648 static_branch_disable(&tcp_have_smc); 3568 3649 smc_inet_exit(); 3569 - tcp_unregister_ulp(&smc_ulp_ops); 3570 3650 sock_unregister(PF_SMC); 3571 3651 smc_core_exit(); 3572 3652 smc_ib_unregister_client(); ··· 3590 3672 MODULE_DESCRIPTION("smc socket address family"); 3591 3673 MODULE_LICENSE("GPL"); 3592 3674 MODULE_ALIAS_NETPROTO(PF_SMC); 3593 - MODULE_ALIAS_TCP_ULP("smc"); 3594 3675 /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */ 3595 3676 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1); 3596 3677 #if IS_ENABLED(CONFIG_IPV6)