Skip to content

Commit a52e95a

Browse files
lcolittidavem330
authored andcommitted
net: diag: allow socket bytecode filters to match socket marks
This allows a privileged process to filter by socket mark when dumping sockets via INET_DIAG_BY_FAMILY. This is useful on systems that use mark-based routing such as Android. The ability to filter socket marks requires CAP_NET_ADMIN, which is consistent with other privileged operations allowed by the SOCK_DIAG interface such as the ability to destroy sockets and the ability to inspect BPF filters attached to packet sockets. Tested: https://android-review.googlesource.com/261350 Signed-off-by: Lorenzo Colitti <[email protected]> Acked-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 627cc4a commit a52e95a

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

include/uapi/linux/inet_diag.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ enum {
7373
INET_DIAG_BC_S_COND,
7474
INET_DIAG_BC_D_COND,
7575
INET_DIAG_BC_DEV_COND, /* u32 ifindex */
76+
INET_DIAG_BC_MARK_COND,
7677
};
7778

7879
struct inet_diag_hostcond {
@@ -82,6 +83,11 @@ struct inet_diag_hostcond {
8283
__be32 addr[0];
8384
};
8485

86+
struct inet_diag_markcond {
87+
__u32 mark;
88+
__u32 mask;
89+
};
90+
8591
/* Base info structure. It contains socket identity (addrs/ports/cookie)
8692
* and, alas, the information shown by netstat. */
8793
struct inet_diag_msg {

net/ipv4/inet_diag.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct inet_diag_entry {
4545
u16 family;
4646
u16 userlocks;
4747
u32 ifindex;
48+
u32 mark;
4849
};
4950

5051
static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -580,6 +581,14 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
580581
yes = 0;
581582
break;
582583
}
584+
case INET_DIAG_BC_MARK_COND: {
585+
struct inet_diag_markcond *cond;
586+
587+
cond = (struct inet_diag_markcond *)(op + 1);
588+
if ((entry->mark & cond->mask) != cond->mark)
589+
yes = 0;
590+
break;
591+
}
583592
}
584593

585594
if (yes) {
@@ -624,6 +633,12 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
624633
entry.dport = ntohs(inet->inet_dport);
625634
entry.ifindex = sk->sk_bound_dev_if;
626635
entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0;
636+
if (sk_fullsock(sk))
637+
entry.mark = sk->sk_mark;
638+
else if (sk->sk_state == TCP_NEW_SYN_RECV)
639+
entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
640+
else
641+
entry.mark = 0;
627642

628643
return inet_diag_bc_run(bc, &entry);
629644
}
@@ -706,8 +721,17 @@ static bool valid_port_comparison(const struct inet_diag_bc_op *op,
706721
return true;
707722
}
708723

709-
static int inet_diag_bc_audit(const struct nlattr *attr)
724+
static bool valid_markcond(const struct inet_diag_bc_op *op, int len,
725+
int *min_len)
710726
{
727+
*min_len += sizeof(struct inet_diag_markcond);
728+
return len >= *min_len;
729+
}
730+
731+
static int inet_diag_bc_audit(const struct nlattr *attr,
732+
const struct sk_buff *skb)
733+
{
734+
bool net_admin = netlink_net_capable(skb, CAP_NET_ADMIN);
711735
const void *bytecode, *bc;
712736
int bytecode_len, len;
713737

@@ -738,6 +762,12 @@ static int inet_diag_bc_audit(const struct nlattr *attr)
738762
if (!valid_port_comparison(bc, len, &min_len))
739763
return -EINVAL;
740764
break;
765+
case INET_DIAG_BC_MARK_COND:
766+
if (!net_admin)
767+
return -EPERM;
768+
if (!valid_markcond(bc, len, &min_len))
769+
return -EINVAL;
770+
break;
741771
case INET_DIAG_BC_AUTO:
742772
case INET_DIAG_BC_JMP:
743773
case INET_DIAG_BC_NOP:
@@ -1030,7 +1060,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
10301060

10311061
attr = nlmsg_find_attr(nlh, hdrlen,
10321062
INET_DIAG_REQ_BYTECODE);
1033-
err = inet_diag_bc_audit(attr);
1063+
err = inet_diag_bc_audit(attr, skb);
10341064
if (err)
10351065
return err;
10361066
}
@@ -1061,7 +1091,7 @@ static int inet_diag_handler_cmd(struct sk_buff *skb, struct nlmsghdr *h)
10611091

10621092
attr = nlmsg_find_attr(h, hdrlen,
10631093
INET_DIAG_REQ_BYTECODE);
1064-
err = inet_diag_bc_audit(attr);
1094+
err = inet_diag_bc_audit(attr, skb);
10651095
if (err)
10661096
return err;
10671097
}

0 commit comments

Comments
 (0)