sock_diag: allow to dump bpf filters
This patch allows to dump BPF filters attached to a socket with SO_ATTACH_FILTER. Note that we check CAP_SYS_ADMIN before allowing to dump this info. For now, only AF_PACKET sockets use this feature. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
76d0eeb1a1
commit
e8d9612c18
4 changed files with 42 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
#ifndef __SOCK_DIAG_H__
|
||||
#define __SOCK_DIAG_H__
|
||||
|
||||
#include <linux/user_namespace.h>
|
||||
#include <uapi/linux/sock_diag.h>
|
||||
|
||||
struct sk_buff;
|
||||
|
@ -22,5 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie);
|
|||
void sock_diag_save_cookie(void *sk, __u32 *cookie);
|
||||
|
||||
int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
|
||||
int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
|
||||
struct sk_buff *skb, int attrtype);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,7 @@ struct packet_diag_req {
|
|||
#define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */
|
||||
#define PACKET_SHOW_FANOUT 0x00000008
|
||||
#define PACKET_SHOW_MEMINFO 0x00000010
|
||||
#define PACKET_SHOW_FILTER 0x00000020
|
||||
|
||||
struct packet_diag_msg {
|
||||
__u8 pdiag_family;
|
||||
|
@ -35,6 +36,7 @@ enum {
|
|||
PACKET_DIAG_FANOUT,
|
||||
PACKET_DIAG_UID,
|
||||
PACKET_DIAG_MEMINFO,
|
||||
PACKET_DIAG_FILTER,
|
||||
|
||||
__PACKET_DIAG_MAX,
|
||||
};
|
||||
|
|
|
@ -49,6 +49,39 @@ int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attrtype)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sock_diag_put_meminfo);
|
||||
|
||||
int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
|
||||
struct sk_buff *skb, int attrtype)
|
||||
{
|
||||
struct nlattr *attr;
|
||||
struct sk_filter *filter;
|
||||
unsigned int len;
|
||||
int err = 0;
|
||||
|
||||
if (!ns_capable(user_ns, CAP_NET_ADMIN)) {
|
||||
nla_reserve(skb, attrtype, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
filter = rcu_dereference(sk->sk_filter);
|
||||
len = filter ? filter->len * sizeof(struct sock_filter) : 0;
|
||||
|
||||
attr = nla_reserve(skb, attrtype, len);
|
||||
if (attr == NULL) {
|
||||
err = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (filter)
|
||||
memcpy(nla_data(attr), filter->insns, len);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(sock_diag_put_filterinfo);
|
||||
|
||||
void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh))
|
||||
{
|
||||
mutex_lock(&sock_diag_table_mutex);
|
||||
|
|
|
@ -170,6 +170,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
|
|||
sock_diag_put_meminfo(sk, skb, PACKET_DIAG_MEMINFO))
|
||||
goto out_nlmsg_trim;
|
||||
|
||||
if ((req->pdiag_show & PACKET_SHOW_FILTER) &&
|
||||
sock_diag_put_filterinfo(user_ns, sk, skb, PACKET_DIAG_FILTER))
|
||||
goto out_nlmsg_trim;
|
||||
|
||||
return nlmsg_end(skb, nlh);
|
||||
|
||||
out_nlmsg_trim:
|
||||
|
|
Loading…
Reference in a new issue