Skip to content

Commit e7b83f2

Browse files
author
Paolo Abeni
committed
Merge branch 'mctp-core-protocol-updates-minor-fixes-tests'
Jeremy Kerr says: ==================== MCTP core protocol updates, minor fixes & tests This series implements some procotol improvements for AF_MCTP, particularly for systems with multiple MCTP networks defined. For those, we need to add the network ID to the tag lookups, which then suggests an updated version of the tag allocate / drop ioctl to allow the net ID to be specified there too. The ioctl change affects uabi, so might warrant some extra attention. There are also a couple of new kunit tests for multiple-net configurations. We have a fix for populating the flow data when fragmenting, and a testcase for that too. Of course, any queries/comments/etc., please let me know! ==================== Link: https://lore.kernel.org/r/cover.1708335994.git.jk@codeconstruct.com.au Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 6d5c365 + d192eaf commit e7b83f2

File tree

9 files changed

+630
-55
lines changed

9 files changed

+630
-55
lines changed

include/net/mctp.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ struct mctp_sock {
8787
};
8888

8989
/* Key for matching incoming packets to sockets or reassembly contexts.
90-
* Packets are matched on (src,dest,tag).
90+
* Packets are matched on (peer EID, local EID, tag).
9191
*
9292
* Lifetime / locking requirements:
9393
*
@@ -133,6 +133,7 @@ struct mctp_sock {
133133
* - through an expiry timeout, on a per-socket timer
134134
*/
135135
struct mctp_sk_key {
136+
unsigned int net;
136137
mctp_eid_t peer_addr;
137138
mctp_eid_t local_addr; /* MCTP_ADDR_ANY for local owned tags */
138139
__u8 tag; /* incoming tag match; invert TO for local */
@@ -254,7 +255,8 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt,
254255

255256
void mctp_key_unref(struct mctp_sk_key *key);
256257
struct mctp_sk_key *mctp_alloc_local_tag(struct mctp_sock *msk,
257-
mctp_eid_t daddr, mctp_eid_t saddr,
258+
unsigned int netid,
259+
mctp_eid_t local, mctp_eid_t peer,
258260
bool manual, u8 *tagp);
259261

260262
/* routing <--> device interface */

include/uapi/linux/mctp.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ struct sockaddr_mctp_ext {
5050

5151
#define SIOCMCTPALLOCTAG (SIOCPROTOPRIVATE + 0)
5252
#define SIOCMCTPDROPTAG (SIOCPROTOPRIVATE + 1)
53+
#define SIOCMCTPALLOCTAG2 (SIOCPROTOPRIVATE + 2)
54+
#define SIOCMCTPDROPTAG2 (SIOCPROTOPRIVATE + 3)
5355

56+
/* Deprecated: use mctp_ioc_tag_ctl2 / TAG2 ioctls instead, which defines the
57+
* MCTP network ID as part of the allocated tag. Using this assumes the default
58+
* net ID for allocated tags, which may not give correct behaviour on system
59+
* with multiple networks configured.
60+
*/
5461
struct mctp_ioc_tag_ctl {
5562
mctp_eid_t peer_addr;
5663

@@ -65,4 +72,29 @@ struct mctp_ioc_tag_ctl {
6572
__u16 flags;
6673
};
6774

75+
struct mctp_ioc_tag_ctl2 {
76+
/* Peer details: network ID, peer EID, local EID. All set by the
77+
* caller.
78+
*
79+
* Local EID must be MCTP_ADDR_NULL or MCTP_ADDR_ANY in current
80+
* kernels.
81+
*/
82+
unsigned int net;
83+
mctp_eid_t peer_addr;
84+
mctp_eid_t local_addr;
85+
86+
/* Set by caller, but no flags defined currently. Must be 0 */
87+
__u16 flags;
88+
89+
/* For SIOCMCTPALLOCTAG2: must be passed as zero, kernel will
90+
* populate with the allocated tag value. Returned tag value will
91+
* always have TO and PREALLOC set.
92+
*
93+
* For SIOCMCTPDROPTAG2: userspace provides tag value to drop, from
94+
* a prior SIOCMCTPALLOCTAG2 call (and so must have TO and PREALLOC set).
95+
*/
96+
__u8 tag;
97+
98+
};
99+
68100
#endif /* __UAPI_MCTP_H */

net/core/skbuff.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6849,6 +6849,14 @@ static struct skb_ext *skb_ext_maybe_cow(struct skb_ext *old,
68496849
for (i = 0; i < sp->len; i++)
68506850
xfrm_state_hold(sp->xvec[i]);
68516851
}
6852+
#endif
6853+
#ifdef CONFIG_MCTP_FLOWS
6854+
if (old_active & (1 << SKB_EXT_MCTP)) {
6855+
struct mctp_flow *flow = skb_ext_get_ptr(old, SKB_EXT_MCTP);
6856+
6857+
if (flow->key)
6858+
refcount_inc(&flow->key->refs);
6859+
}
68526860
#endif
68536861
__skb_ext_put(old);
68546862
return new;

net/mctp/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ menuconfig MCTP
1414

1515
config MCTP_TEST
1616
bool "MCTP core tests" if !KUNIT_ALL_TESTS
17+
select MCTP_FLOWS
1718
depends on MCTP=y && KUNIT=y
1819
default KUNIT_ALL_TESTS
1920

net/mctp/af_mctp.c

Lines changed: 97 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -350,30 +350,102 @@ static int mctp_getsockopt(struct socket *sock, int level, int optname,
350350
return -EINVAL;
351351
}
352352

353-
static int mctp_ioctl_alloctag(struct mctp_sock *msk, unsigned long arg)
353+
/* helpers for reading/writing the tag ioc, handling compatibility across the
354+
* two versions, and some basic API error checking
355+
*/
356+
static int mctp_ioctl_tag_copy_from_user(unsigned long arg,
357+
struct mctp_ioc_tag_ctl2 *ctl,
358+
bool tagv2)
359+
{
360+
struct mctp_ioc_tag_ctl ctl_compat;
361+
unsigned long size;
362+
void *ptr;
363+
int rc;
364+
365+
if (tagv2) {
366+
size = sizeof(*ctl);
367+
ptr = ctl;
368+
} else {
369+
size = sizeof(ctl_compat);
370+
ptr = &ctl_compat;
371+
}
372+
373+
rc = copy_from_user(ptr, (void __user *)arg, size);
374+
if (rc)
375+
return -EFAULT;
376+
377+
if (!tagv2) {
378+
/* compat, using defaults for new fields */
379+
ctl->net = MCTP_INITIAL_DEFAULT_NET;
380+
ctl->peer_addr = ctl_compat.peer_addr;
381+
ctl->local_addr = MCTP_ADDR_ANY;
382+
ctl->flags = ctl_compat.flags;
383+
ctl->tag = ctl_compat.tag;
384+
}
385+
386+
if (ctl->flags)
387+
return -EINVAL;
388+
389+
if (ctl->local_addr != MCTP_ADDR_ANY &&
390+
ctl->local_addr != MCTP_ADDR_NULL)
391+
return -EINVAL;
392+
393+
return 0;
394+
}
395+
396+
static int mctp_ioctl_tag_copy_to_user(unsigned long arg,
397+
struct mctp_ioc_tag_ctl2 *ctl,
398+
bool tagv2)
399+
{
400+
struct mctp_ioc_tag_ctl ctl_compat;
401+
unsigned long size;
402+
void *ptr;
403+
int rc;
404+
405+
if (tagv2) {
406+
ptr = ctl;
407+
size = sizeof(*ctl);
408+
} else {
409+
ctl_compat.peer_addr = ctl->peer_addr;
410+
ctl_compat.tag = ctl->tag;
411+
ctl_compat.flags = ctl->flags;
412+
413+
ptr = &ctl_compat;
414+
size = sizeof(ctl_compat);
415+
}
416+
417+
rc = copy_to_user((void __user *)arg, ptr, size);
418+
if (rc)
419+
return -EFAULT;
420+
421+
return 0;
422+
}
423+
424+
static int mctp_ioctl_alloctag(struct mctp_sock *msk, bool tagv2,
425+
unsigned long arg)
354426
{
355427
struct net *net = sock_net(&msk->sk);
356428
struct mctp_sk_key *key = NULL;
357-
struct mctp_ioc_tag_ctl ctl;
429+
struct mctp_ioc_tag_ctl2 ctl;
358430
unsigned long flags;
359431
u8 tag;
432+
int rc;
360433

361-
if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl)))
362-
return -EFAULT;
434+
rc = mctp_ioctl_tag_copy_from_user(arg, &ctl, tagv2);
435+
if (rc)
436+
return rc;
363437

364438
if (ctl.tag)
365439
return -EINVAL;
366440

367-
if (ctl.flags)
368-
return -EINVAL;
369-
370-
key = mctp_alloc_local_tag(msk, ctl.peer_addr, MCTP_ADDR_ANY,
371-
true, &tag);
441+
key = mctp_alloc_local_tag(msk, ctl.net, MCTP_ADDR_ANY,
442+
ctl.peer_addr, true, &tag);
372443
if (IS_ERR(key))
373444
return PTR_ERR(key);
374445

375446
ctl.tag = tag | MCTP_TAG_OWNER | MCTP_TAG_PREALLOC;
376-
if (copy_to_user((void __user *)arg, &ctl, sizeof(ctl))) {
447+
rc = mctp_ioctl_tag_copy_to_user(arg, &ctl, tagv2);
448+
if (rc) {
377449
unsigned long fl2;
378450
/* Unwind our key allocation: the keys list lock needs to be
379451
* taken before the individual key locks, and we need a valid
@@ -385,28 +457,27 @@ static int mctp_ioctl_alloctag(struct mctp_sock *msk, unsigned long arg)
385457
__mctp_key_remove(key, net, fl2, MCTP_TRACE_KEY_DROPPED);
386458
mctp_key_unref(key);
387459
spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
388-
return -EFAULT;
460+
return rc;
389461
}
390462

391463
mctp_key_unref(key);
392464
return 0;
393465
}
394466

395-
static int mctp_ioctl_droptag(struct mctp_sock *msk, unsigned long arg)
467+
static int mctp_ioctl_droptag(struct mctp_sock *msk, bool tagv2,
468+
unsigned long arg)
396469
{
397470
struct net *net = sock_net(&msk->sk);
398-
struct mctp_ioc_tag_ctl ctl;
471+
struct mctp_ioc_tag_ctl2 ctl;
399472
unsigned long flags, fl2;
400473
struct mctp_sk_key *key;
401474
struct hlist_node *tmp;
402475
int rc;
403476
u8 tag;
404477

405-
if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl)))
406-
return -EFAULT;
407-
408-
if (ctl.flags)
409-
return -EINVAL;
478+
rc = mctp_ioctl_tag_copy_from_user(arg, &ctl, tagv2);
479+
if (rc)
480+
return rc;
410481

411482
/* Must be a local tag, TO set, preallocated */
412483
if ((ctl.tag & ~MCTP_TAG_MASK) != (MCTP_TAG_OWNER | MCTP_TAG_PREALLOC))
@@ -422,6 +493,7 @@ static int mctp_ioctl_droptag(struct mctp_sock *msk, unsigned long arg)
422493
*/
423494
spin_lock_irqsave(&key->lock, fl2);
424495
if (key->manual_alloc &&
496+
ctl.net == key->net &&
425497
ctl.peer_addr == key->peer_addr &&
426498
tag == key->tag) {
427499
__mctp_key_remove(key, net, fl2,
@@ -439,12 +511,17 @@ static int mctp_ioctl_droptag(struct mctp_sock *msk, unsigned long arg)
439511
static int mctp_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
440512
{
441513
struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
514+
bool tagv2 = false;
442515

443516
switch (cmd) {
517+
case SIOCMCTPALLOCTAG2:
444518
case SIOCMCTPALLOCTAG:
445-
return mctp_ioctl_alloctag(msk, arg);
519+
tagv2 = cmd == SIOCMCTPALLOCTAG2;
520+
return mctp_ioctl_alloctag(msk, tagv2, arg);
446521
case SIOCMCTPDROPTAG:
447-
return mctp_ioctl_droptag(msk, arg);
522+
case SIOCMCTPDROPTAG2:
523+
tagv2 = cmd == SIOCMCTPDROPTAG2;
524+
return mctp_ioctl_droptag(msk, tagv2, arg);
448525
}
449526

450527
return -EINVAL;

0 commit comments

Comments
 (0)