aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gschwantner <tharre3@gmail.com>2018-07-25 22:58:17 +0200
committerThomas Gschwantner <tharre3@gmail.com>2018-08-10 21:19:56 +0200
commit76b863124231fb48882ea8c7d46f21583f3b3dff (patch)
tree8365bd10edc101f2abded142f790bdc6ed895458
parentnet: sk_buff: introduce skb_memzero_explicit (diff)
downloadlinux-dev-tg/skb_memzero.tar.xz
linux-dev-tg/skb_memzero.zip
[WIP] net: Introduce SO_ZERO_ON_FREEtg/skb_memzero
This option causes all skbs owned by the socket to be zeored out by skb_memzero_explicit once it's freed. This is useful if the skb contains secrets that should be cleared from memory as soon as possible. Signed-off-by: Thomas Gschwantner <tharre3@gmail.com>
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/ia64/include/uapi/asm/socket.h2
-rw-r--r--arch/mips/include/uapi/asm/socket.h2
-rw-r--r--arch/parisc/include/uapi/asm/socket.h2
-rw-r--r--arch/s390/include/uapi/asm/socket.h2
-rw-r--r--arch/sparc/include/uapi/asm/socket.h2
-rw-r--r--arch/xtensa/include/uapi/asm/socket.h2
-rw-r--r--include/linux/skbuff.h12
-rw-r--r--include/net/sock.h1
-rw-r--r--include/uapi/asm-generic/socket.h2
-rw-r--r--net/core/skbuff.c5
-rw-r--r--net/core/sock.c16
-rw-r--r--net/netlink/af_netlink.c6
-rw-r--r--net/unix/af_unix.c10
14 files changed, 66 insertions, 0 deletions
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index be14f16149d5..ffe83d1e504a 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -112,4 +112,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 3efba40adc54..d1d01a2e744f 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -114,4 +114,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 49c3d4795963..82d73b40029c 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -123,4 +123,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 1d0fdc3b5d22..5f208ee3c717 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -104,4 +104,6 @@
#define SO_ZEROCOPY 0x4035
+#define SO_ZERO_ON_FREE 0x4036
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 3510c0fd06f4..cd2fc7aad853 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -111,4 +111,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index d58520c2e6ff..9c886b9ba9cd 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -101,6 +101,8 @@
#define SO_ZEROCOPY 0x003e
+#define SO_ZERO_ON_FREE 0x003f
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 75a07b8119a9..3d63e4da7c3a 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -116,4 +116,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 0f8b0433b943..6cdcce4fad22 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -641,6 +641,7 @@ typedef unsigned char *sk_buff_data_t;
* @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS
* @csum_not_inet: use CRC32c to resolve CHECKSUM_PARTIAL
* @dst_pending_confirm: need to confirm neighbour
+ * @zero_on_free: zero all data when freeing skb
* @napi_id: id of the NAPI struct this skb came from
* @secmark: security marking
* @mark: Generic packet mark
@@ -792,6 +793,8 @@ struct sk_buff {
__u8 tc_from_ingress:1;
#endif
+ __u8 zero_on_free:1;
+
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#endif
@@ -1052,6 +1055,15 @@ int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg
int __must_check skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg,
int offset, int len);
void skb_memzero_explicit(struct sk_buff *skb);
+
+/**
+ * skb_memzero_on_free - Zero out skb once it is freed
+ * @skb: buffer to zero out
+ */
+static inline void skb_memzero_on_free(struct sk_buff *skb)
+{
+ skb->zero_on_free = 1;
+}
int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
int __skb_pad(struct sk_buff *skb, int pad, bool free_on_error);
diff --git a/include/net/sock.h b/include/net/sock.h
index b3b75419eafe..a6e6e64c3e21 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -783,6 +783,7 @@ enum sock_flags {
SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */
SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
+ SOCK_ZERO_ON_FREE,
};
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 0ae758c90e54..73ad6f3f41ed 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -107,4 +107,6 @@
#define SO_ZEROCOPY 60
+#define SO_ZERO_ON_FREE 61
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index df926fc0dc0b..023568142c52 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -560,6 +560,11 @@ static void skb_release_data(struct sk_buff *skb)
&shinfo->dataref))
return;
+ if (unlikely(skb->zero_on_free)) {
+ pr_warn("Zeroing memory...\n");
+ skb_memzero_explicit(skb);
+ }
+
for (i = 0; i < shinfo->nr_frags; i++)
__skb_frag_unref(&shinfo->frags[i]);
diff --git a/net/core/sock.c b/net/core/sock.c
index bc2d7a37297f..2210a7e26f6c 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -472,8 +472,15 @@ int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
__skb_queue_tail(list, skb);
spin_unlock_irqrestore(&list->lock, flags);
+ if (sock_flag(sk, SOCK_ZERO_ON_FREE)) {
+ /* if (test_bit(SOCK_ZERO_ON_FREE, &sk->sk_flags)) { */
+ pr_warn("zero_on_free __sock_queue_rcv_skb\n");
+ skb_memzero_on_free(skb);
+ }
+
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk);
+
return 0;
}
EXPORT_SYMBOL(__sock_queue_rcv_skb);
@@ -1070,6 +1077,11 @@ set_rcvbuf:
}
break;
+ case SO_ZERO_ON_FREE:
+ pr_warn("Set SOCK_ZERO_ON_FREE\n");
+ sock_valbool_flag(sk, SOCK_ZERO_ON_FREE, valbool);
+ break;
+
default:
ret = -ENOPROTOOPT;
break;
@@ -1403,6 +1415,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
v.val = sock_flag(sk, SOCK_ZEROCOPY);
break;
+ case SO_ZERO_ON_FREE:
+ v.val = sock_flag(sk, SOCK_ZERO_ON_FREE);
+ break;
+
default:
/* We implement the SO_SNDLOWAT etc to not be settable
* (1003.1g 7).
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 393573a99a5a..11f967ce8d69 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1989,6 +1989,12 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
}
scm_recv(sock, msg, &scm, flags);
+
+ /* if (test_bit(SOCK_ZERO_ON_FREE, &sock->flags)) { */
+ if (sock_flag(sk, SOCK_ZERO_ON_FREE)) {
+ pr_warn("zero_on_free af_netlink\n");
+ skb_memzero_on_free(skb);
+ }
out:
netlink_rcv_wake(sk);
return err ? : copied;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e5473c03d667..f6b620cdfb64 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1836,6 +1836,11 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
if (err < 0)
return err;
+ if (sock_flag(sk, SOCK_ZERO_ON_FREE)) {
+ pr_warn("zero_on_free af_unix sendmsg\n");
+ skb_memzero_on_free(skb);
+ }
+
err = -EOPNOTSUPP;
if (msg->msg_flags&MSG_OOB)
goto out_err;
@@ -2170,6 +2175,11 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
scm_recv(sock, msg, &scm, flags);
+ if (sock_flag(sk, SOCK_ZERO_ON_FREE)) {
+ pr_warn("zero_on_free af_unix\n");
+ skb_memzero_on_free(skb);
+ }
+
out_free:
skb_free_datagram(sk, skb);
mutex_unlock(&u->iolock);