af_mctp.c (542898c5aa5c6a3179dffb1d1606884a63f75fed) | af_mctp.c (63ed1aab3d40aa61aaa66819bdce9377ac7f40fa) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Management Component Transport Protocol (MCTP) 4 * 5 * Copyright (c) 2021 Code Construct 6 * Copyright (c) 2021 Google 7 */ 8 | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Management Component Transport Protocol (MCTP) 4 * 5 * Copyright (c) 2021 Code Construct 6 * Copyright (c) 2021 Google 7 */ 8 |
9#include <linux/compat.h> |
|
9#include <linux/if_arp.h> 10#include <linux/net.h> 11#include <linux/mctp.h> 12#include <linux/module.h> 13#include <linux/socket.h> 14 15#include <net/mctp.h> 16#include <net/mctpdevice.h> 17#include <net/sock.h> 18 19#define CREATE_TRACE_POINTS 20#include <trace/events/mctp.h> 21 22/* socket implementation */ 23 | 10#include <linux/if_arp.h> 11#include <linux/net.h> 12#include <linux/mctp.h> 13#include <linux/module.h> 14#include <linux/socket.h> 15 16#include <net/mctp.h> 17#include <net/mctpdevice.h> 18#include <net/sock.h> 19 20#define CREATE_TRACE_POINTS 21#include <trace/events/mctp.h> 22 23/* socket implementation */ 24 |
25static void mctp_sk_expire_keys(struct timer_list *timer); 26 |
|
24static int mctp_release(struct socket *sock) 25{ 26 struct sock *sk = sock->sk; 27 28 if (sk) { 29 sock->sk = NULL; 30 sk->sk_prot->close(sk, 0); 31 } --- 62 unchanged lines hidden (view full) --- 94 int rc, addrlen = msg->msg_namelen; 95 struct sock *sk = sock->sk; 96 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 97 struct mctp_skb_cb *cb; 98 struct mctp_route *rt; 99 struct sk_buff *skb; 100 101 if (addr) { | 27static int mctp_release(struct socket *sock) 28{ 29 struct sock *sk = sock->sk; 30 31 if (sk) { 32 sock->sk = NULL; 33 sk->sk_prot->close(sk, 0); 34 } --- 62 unchanged lines hidden (view full) --- 97 int rc, addrlen = msg->msg_namelen; 98 struct sock *sk = sock->sk; 99 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 100 struct mctp_skb_cb *cb; 101 struct mctp_route *rt; 102 struct sk_buff *skb; 103 104 if (addr) { |
105 const u8 tagbits = MCTP_TAG_MASK | MCTP_TAG_OWNER | 106 MCTP_TAG_PREALLOC; 107 |
|
102 if (addrlen < sizeof(struct sockaddr_mctp)) 103 return -EINVAL; 104 if (addr->smctp_family != AF_MCTP) 105 return -EINVAL; 106 if (!mctp_sockaddr_is_ok(addr)) 107 return -EINVAL; | 108 if (addrlen < sizeof(struct sockaddr_mctp)) 109 return -EINVAL; 110 if (addr->smctp_family != AF_MCTP) 111 return -EINVAL; 112 if (!mctp_sockaddr_is_ok(addr)) 113 return -EINVAL; |
108 if (addr->smctp_tag & ~(MCTP_TAG_MASK | MCTP_TAG_OWNER)) | 114 if (addr->smctp_tag & ~tagbits) |
109 return -EINVAL; | 115 return -EINVAL; |
116 /* can't preallocate a non-owned tag */ 117 if (addr->smctp_tag & MCTP_TAG_PREALLOC && 118 !(addr->smctp_tag & MCTP_TAG_OWNER)) 119 return -EINVAL; |
|
110 111 } else { 112 /* TODO: connect()ed sockets */ 113 return -EDESTADDRREQ; 114 } 115 116 if (!capable(CAP_NET_RAW)) 117 return -EACCES; --- 125 unchanged lines hidden (view full) --- 243 if (flags & MSG_TRUNC) 244 rc = msglen; 245 246out_free: 247 skb_free_datagram(sk, skb); 248 return rc; 249} 250 | 120 121 } else { 122 /* TODO: connect()ed sockets */ 123 return -EDESTADDRREQ; 124 } 125 126 if (!capable(CAP_NET_RAW)) 127 return -EACCES; --- 125 unchanged lines hidden (view full) --- 253 if (flags & MSG_TRUNC) 254 rc = msglen; 255 256out_free: 257 skb_free_datagram(sk, skb); 258 return rc; 259} 260 |
261/* We're done with the key; invalidate, stop reassembly, and remove from lists. 262 */ 263static void __mctp_key_remove(struct mctp_sk_key *key, struct net *net, 264 unsigned long flags, unsigned long reason) 265__releases(&key->lock) 266__must_hold(&net->mctp.keys_lock) 267{ 268 struct sk_buff *skb; 269 270 trace_mctp_key_release(key, reason); 271 skb = key->reasm_head; 272 key->reasm_head = NULL; 273 key->reasm_dead = true; 274 key->valid = false; 275 mctp_dev_release_key(key->dev, key); 276 spin_unlock_irqrestore(&key->lock, flags); 277 278 hlist_del(&key->hlist); 279 hlist_del(&key->sklist); 280 281 /* unref for the lists */ 282 mctp_key_unref(key); 283 284 kfree_skb(skb); 285} 286 |
|
251static int mctp_setsockopt(struct socket *sock, int level, int optname, 252 sockptr_t optval, unsigned int optlen) 253{ 254 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); 255 int val; 256 257 if (level != SOL_MCTP) 258 return -EINVAL; --- 29 unchanged lines hidden (view full) --- 288 if (copy_to_user(optval, &val, len)) 289 return -EFAULT; 290 return 0; 291 } 292 293 return -EINVAL; 294} 295 | 287static int mctp_setsockopt(struct socket *sock, int level, int optname, 288 sockptr_t optval, unsigned int optlen) 289{ 290 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); 291 int val; 292 293 if (level != SOL_MCTP) 294 return -EINVAL; --- 29 unchanged lines hidden (view full) --- 324 if (copy_to_user(optval, &val, len)) 325 return -EFAULT; 326 return 0; 327 } 328 329 return -EINVAL; 330} 331 |
332static int mctp_ioctl_alloctag(struct mctp_sock *msk, unsigned long arg) 333{ 334 struct net *net = sock_net(&msk->sk); 335 struct mctp_sk_key *key = NULL; 336 struct mctp_ioc_tag_ctl ctl; 337 unsigned long flags; 338 u8 tag; 339 340 if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl))) 341 return -EFAULT; 342 343 if (ctl.tag) 344 return -EINVAL; 345 346 if (ctl.flags) 347 return -EINVAL; 348 349 key = mctp_alloc_local_tag(msk, ctl.peer_addr, MCTP_ADDR_ANY, 350 true, &tag); 351 if (IS_ERR(key)) 352 return PTR_ERR(key); 353 354 ctl.tag = tag | MCTP_TAG_OWNER | MCTP_TAG_PREALLOC; 355 if (copy_to_user((void __user *)arg, &ctl, sizeof(ctl))) { 356 spin_lock_irqsave(&key->lock, flags); 357 __mctp_key_remove(key, net, flags, MCTP_TRACE_KEY_DROPPED); 358 mctp_key_unref(key); 359 return -EFAULT; 360 } 361 362 mctp_key_unref(key); 363 return 0; 364} 365 366static int mctp_ioctl_droptag(struct mctp_sock *msk, unsigned long arg) 367{ 368 struct net *net = sock_net(&msk->sk); 369 struct mctp_ioc_tag_ctl ctl; 370 unsigned long flags, fl2; 371 struct mctp_sk_key *key; 372 struct hlist_node *tmp; 373 int rc; 374 u8 tag; 375 376 if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl))) 377 return -EFAULT; 378 379 if (ctl.flags) 380 return -EINVAL; 381 382 /* Must be a local tag, TO set, preallocated */ 383 if ((ctl.tag & ~MCTP_TAG_MASK) != (MCTP_TAG_OWNER | MCTP_TAG_PREALLOC)) 384 return -EINVAL; 385 386 tag = ctl.tag & MCTP_TAG_MASK; 387 rc = -EINVAL; 388 389 spin_lock_irqsave(&net->mctp.keys_lock, flags); 390 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { 391 /* we do an irqsave here, even though we know the irq state, 392 * so we have the flags to pass to __mctp_key_remove 393 */ 394 spin_lock_irqsave(&key->lock, fl2); 395 if (key->manual_alloc && 396 ctl.peer_addr == key->peer_addr && 397 tag == key->tag) { 398 __mctp_key_remove(key, net, fl2, 399 MCTP_TRACE_KEY_DROPPED); 400 rc = 0; 401 } else { 402 spin_unlock_irqrestore(&key->lock, fl2); 403 } 404 } 405 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); 406 407 return rc; 408} 409 410static int mctp_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 411{ 412 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); 413 414 switch (cmd) { 415 case SIOCMCTPALLOCTAG: 416 return mctp_ioctl_alloctag(msk, arg); 417 case SIOCMCTPDROPTAG: 418 return mctp_ioctl_droptag(msk, arg); 419 } 420 421 return -EINVAL; 422} 423 424#ifdef CONFIG_COMPAT 425static int mctp_compat_ioctl(struct socket *sock, unsigned int cmd, 426 unsigned long arg) 427{ 428 void __user *argp = compat_ptr(arg); 429 430 switch (cmd) { 431 /* These have compatible ptr layouts */ 432 case SIOCMCTPALLOCTAG: 433 case SIOCMCTPDROPTAG: 434 return mctp_ioctl(sock, cmd, (unsigned long)argp); 435 } 436 437 return -ENOIOCTLCMD; 438} 439#endif 440 |
|
296static const struct proto_ops mctp_dgram_ops = { 297 .family = PF_MCTP, 298 .release = mctp_release, 299 .bind = mctp_bind, 300 .connect = sock_no_connect, 301 .socketpair = sock_no_socketpair, 302 .accept = sock_no_accept, 303 .getname = sock_no_getname, 304 .poll = datagram_poll, | 441static const struct proto_ops mctp_dgram_ops = { 442 .family = PF_MCTP, 443 .release = mctp_release, 444 .bind = mctp_bind, 445 .connect = sock_no_connect, 446 .socketpair = sock_no_socketpair, 447 .accept = sock_no_accept, 448 .getname = sock_no_getname, 449 .poll = datagram_poll, |
305 .ioctl = sock_no_ioctl, | 450 .ioctl = mctp_ioctl, |
306 .gettstamp = sock_gettstamp, 307 .listen = sock_no_listen, 308 .shutdown = sock_no_shutdown, 309 .setsockopt = mctp_setsockopt, 310 .getsockopt = mctp_getsockopt, 311 .sendmsg = mctp_sendmsg, 312 .recvmsg = mctp_recvmsg, 313 .mmap = sock_no_mmap, 314 .sendpage = sock_no_sendpage, | 451 .gettstamp = sock_gettstamp, 452 .listen = sock_no_listen, 453 .shutdown = sock_no_shutdown, 454 .setsockopt = mctp_setsockopt, 455 .getsockopt = mctp_getsockopt, 456 .sendmsg = mctp_sendmsg, 457 .recvmsg = mctp_recvmsg, 458 .mmap = sock_no_mmap, 459 .sendpage = sock_no_sendpage, |
460#ifdef CONFIG_COMPAT 461 .compat_ioctl = mctp_compat_ioctl, 462#endif |
|
315}; 316 317static void mctp_sk_expire_keys(struct timer_list *timer) 318{ 319 struct mctp_sock *msk = container_of(timer, struct mctp_sock, 320 key_expiry); 321 struct net *net = sock_net(&msk->sk); | 463}; 464 465static void mctp_sk_expire_keys(struct timer_list *timer) 466{ 467 struct mctp_sock *msk = container_of(timer, struct mctp_sock, 468 key_expiry); 469 struct net *net = sock_net(&msk->sk); |
322 unsigned long next_expiry, flags; | 470 unsigned long next_expiry, flags, fl2; |
323 struct mctp_sk_key *key; 324 struct hlist_node *tmp; 325 bool next_expiry_valid = false; 326 327 spin_lock_irqsave(&net->mctp.keys_lock, flags); 328 329 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { | 471 struct mctp_sk_key *key; 472 struct hlist_node *tmp; 473 bool next_expiry_valid = false; 474 475 spin_lock_irqsave(&net->mctp.keys_lock, flags); 476 477 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { |
330 spin_lock(&key->lock); | 478 /* don't expire. manual_alloc is immutable, no locking 479 * required. 480 */ 481 if (key->manual_alloc) 482 continue; |
331 | 483 |
484 spin_lock_irqsave(&key->lock, fl2); |
|
332 if (!time_after_eq(key->expiry, jiffies)) { | 485 if (!time_after_eq(key->expiry, jiffies)) { |
333 trace_mctp_key_release(key, MCTP_TRACE_KEY_TIMEOUT); 334 key->valid = false; 335 hlist_del_rcu(&key->hlist); 336 hlist_del_rcu(&key->sklist); 337 spin_unlock(&key->lock); 338 mctp_key_unref(key); | 486 __mctp_key_remove(key, net, fl2, 487 MCTP_TRACE_KEY_TIMEOUT); |
339 continue; 340 } 341 342 if (next_expiry_valid) { 343 if (time_before(key->expiry, next_expiry)) 344 next_expiry = key->expiry; 345 } else { 346 next_expiry = key->expiry; 347 next_expiry_valid = true; 348 } | 488 continue; 489 } 490 491 if (next_expiry_valid) { 492 if (time_before(key->expiry, next_expiry)) 493 next_expiry = key->expiry; 494 } else { 495 next_expiry = key->expiry; 496 next_expiry_valid = true; 497 } |
349 spin_unlock(&key->lock); | 498 spin_unlock_irqrestore(&key->lock, fl2); |
350 } 351 352 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); 353 354 if (next_expiry_valid) 355 mod_timer(timer, next_expiry); 356} 357 --- 24 unchanged lines hidden (view full) --- 382 383 return 0; 384} 385 386static void mctp_sk_unhash(struct sock *sk) 387{ 388 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 389 struct net *net = sock_net(sk); | 499 } 500 501 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); 502 503 if (next_expiry_valid) 504 mod_timer(timer, next_expiry); 505} 506 --- 24 unchanged lines hidden (view full) --- 531 532 return 0; 533} 534 535static void mctp_sk_unhash(struct sock *sk) 536{ 537 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 538 struct net *net = sock_net(sk); |
539 unsigned long flags, fl2; |
|
390 struct mctp_sk_key *key; 391 struct hlist_node *tmp; | 540 struct mctp_sk_key *key; 541 struct hlist_node *tmp; |
392 unsigned long flags; | |
393 394 /* remove from any type-based binds */ 395 mutex_lock(&net->mctp.bind_lock); 396 sk_del_node_init_rcu(sk); 397 mutex_unlock(&net->mctp.bind_lock); 398 399 /* remove tag allocations */ 400 spin_lock_irqsave(&net->mctp.keys_lock, flags); 401 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { | 542 543 /* remove from any type-based binds */ 544 mutex_lock(&net->mctp.bind_lock); 545 sk_del_node_init_rcu(sk); 546 mutex_unlock(&net->mctp.bind_lock); 547 548 /* remove tag allocations */ 549 spin_lock_irqsave(&net->mctp.keys_lock, flags); 550 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { |
402 hlist_del(&key->sklist); 403 hlist_del(&key->hlist); 404 405 trace_mctp_key_release(key, MCTP_TRACE_KEY_CLOSED); 406 407 spin_lock(&key->lock); 408 kfree_skb(key->reasm_head); 409 key->reasm_head = NULL; 410 key->reasm_dead = true; 411 key->valid = false; 412 spin_unlock(&key->lock); 413 414 /* key is no longer on the lookup lists, unref */ 415 mctp_key_unref(key); | 551 spin_lock_irqsave(&key->lock, fl2); 552 __mctp_key_remove(key, net, fl2, MCTP_TRACE_KEY_CLOSED); |
416 } 417 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); 418} 419 420static struct proto mctp_proto = { 421 .name = "MCTP", 422 .owner = THIS_MODULE, 423 .obj_size = sizeof(struct mctp_sock), --- 109 unchanged lines hidden --- | 553 } 554 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); 555} 556 557static struct proto mctp_proto = { 558 .name = "MCTP", 559 .owner = THIS_MODULE, 560 .obj_size = sizeof(struct mctp_sock), --- 109 unchanged lines hidden --- |