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 ---