inet_diag: add support for cgroup filter
authorDmitry Yakunin <zeil@yandex-team.ru>
Thu, 30 Apr 2020 15:51:15 +0000 (18:51 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Apr 2020 19:54:02 +0000 (12:54 -0700)
This patch adds ability to filter sockets based on cgroup v2 ID.
Such filter is helpful in ss utility for filtering sockets by
cgroup pathname.

Signed-off-by: Dmitry Yakunin <zeil@yandex-team.ru>
Reviewed-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/inet_diag.h
net/ipv4/inet_diag.c

index c9b1e55..e6f183e 100644 (file)
@@ -96,6 +96,7 @@ enum {
        INET_DIAG_BC_MARK_COND,
        INET_DIAG_BC_S_EQ,
        INET_DIAG_BC_D_EQ,
+       INET_DIAG_BC_CGROUP_COND,   /* u64 cgroup v2 ID */
 };
 
 struct inet_diag_hostcond {
index 9c4c315..0034092 100644 (file)
@@ -43,6 +43,9 @@ struct inet_diag_entry {
        u16 userlocks;
        u32 ifindex;
        u32 mark;
+#ifdef CONFIG_SOCK_CGROUP_DATA
+       u64 cgroup_id;
+#endif
 };
 
 static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -682,6 +685,16 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
                                yes = 0;
                        break;
                }
+#ifdef CONFIG_SOCK_CGROUP_DATA
+               case INET_DIAG_BC_CGROUP_COND: {
+                       u64 cgroup_id;
+
+                       cgroup_id = get_unaligned((const u64 *)(op + 1));
+                       if (cgroup_id != entry->cgroup_id)
+                               yes = 0;
+                       break;
+               }
+#endif
                }
 
                if (yes) {
@@ -732,6 +745,9 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
                entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
        else
                entry.mark = 0;
+#ifdef CONFIG_SOCK_CGROUP_DATA
+       entry.cgroup_id = cgroup_id(sock_cgroup_ptr(&sk->sk_cgrp_data));
+#endif
 
        return inet_diag_bc_run(bc, &entry);
 }
@@ -821,6 +837,15 @@ static bool valid_markcond(const struct inet_diag_bc_op *op, int len,
        return len >= *min_len;
 }
 
+#ifdef CONFIG_SOCK_CGROUP_DATA
+static bool valid_cgroupcond(const struct inet_diag_bc_op *op, int len,
+                            int *min_len)
+{
+       *min_len += sizeof(u64);
+       return len >= *min_len;
+}
+#endif
+
 static int inet_diag_bc_audit(const struct nlattr *attr,
                              const struct sk_buff *skb)
 {
@@ -863,6 +888,12 @@ static int inet_diag_bc_audit(const struct nlattr *attr,
                        if (!valid_markcond(bc, len, &min_len))
                                return -EINVAL;
                        break;
+#ifdef CONFIG_SOCK_CGROUP_DATA
+               case INET_DIAG_BC_CGROUP_COND:
+                       if (!valid_cgroupcond(bc, len, &min_len))
+                               return -EINVAL;
+                       break;
+#endif
                case INET_DIAG_BC_AUTO:
                case INET_DIAG_BC_JMP:
                case INET_DIAG_BC_NOP: