From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linutronix.de (146.0.238.70:993) by crypto-ml.lab.linutronix.de with IMAP4-SSL for ; 21 Jan 2019 19:54:49 -0000 Received: from mga11.intel.com ([192.55.52.93]) by Galois.linutronix.de with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1gkeqY-0003NL-Jp for speck@linutronix.de; Sat, 19 Jan 2019 01:50:51 +0100 From: Andi Kleen Subject: [MODERATED] [PATCH v5 22/27] MDSv5 24 Date: Fri, 18 Jan 2019 16:50:37 -0800 Message-Id: <5fc3209d2880402d332ec93cf076467b3706a401.1547858934.git.ak@linux.intel.com> In-Reply-To: References: In-Reply-To: References: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit MIME-Version: 1.0 To: speck@linutronix.de Cc: Andi Kleen List-ID: Instrument some strategic skbuff functions that either touch packet data directly, or are likely followed by a user data touch like a memcpy, to schedule a cpu clear on next kernel exit. This is only done inside interrupts, outside we assume it only touches the current processes' data. In principle network data should be encrypted anyways, but it's better to not leak it. This provides protection for the network softirq. Needs more auditing. Signed-off-by: Andi Kleen --- include/linux/skbuff.h | 2 ++ net/core/skbuff.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 93f56fddd92a..5e147afa07e4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -40,6 +40,7 @@ #include #include #include +#include /* The interface for checksum offload between the stack and networking drivers * is as follows... @@ -2093,6 +2094,7 @@ static inline void *__skb_put(struct sk_buff *skb, unsigned int len) SKB_LINEAR_ASSERT(skb); skb->tail += len; skb->len += len; + lazy_clear_cpu_interrupt(); return tmp; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 37317ffec146..eda9ef0ff63d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1189,6 +1189,9 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) if (!num_frags) goto release; + /* Likely to copy user data */ + lazy_clear_cpu_interrupt(); + new_frags = (__skb_pagelen(skb) + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < new_frags; i++) { page = alloc_page(gfp_mask); @@ -1353,6 +1356,9 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) if (!n) return NULL; + /* Copies user data */ + lazy_clear_cpu_interrupt(); + /* Set the data pointer */ skb_reserve(n, headerlen); /* Set the tail pointer and length */ @@ -1588,6 +1594,9 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, if (!n) return NULL; + /* May copy user data */ + lazy_clear_cpu_interrupt(); + skb_reserve(n, newheadroom); /* Set the tail pointer and length */ @@ -1676,6 +1685,8 @@ EXPORT_SYMBOL(__skb_pad); void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) { + /* Likely to be followed by a user data copy */ + lazy_clear_cpu_interrupt(); if (tail != skb) { skb->data_len += len; skb->len += len; @@ -1701,6 +1712,8 @@ void *skb_put(struct sk_buff *skb, unsigned int len) skb->len += len; if (unlikely(skb->tail > skb->end)) skb_over_panic(skb, len, __builtin_return_address(0)); + /* Likely to be followed by a user data copy */ + lazy_clear_cpu_interrupt(); return tmp; } EXPORT_SYMBOL(skb_put); @@ -1720,6 +1733,7 @@ void *skb_push(struct sk_buff *skb, unsigned int len) skb->len += len; if (unlikely(skb->data < skb->head)) skb_under_panic(skb, len, __builtin_return_address(0)); + /* No clear cpu, assume this is only header data */ return skb->data; } EXPORT_SYMBOL(skb_push); @@ -2026,6 +2040,9 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) struct sk_buff *frag_iter; int i, copy; + /* Copies user data */ + lazy_clear_cpu_interrupt(); + if (offset > (int)skb->len - len) goto fault; @@ -2387,6 +2404,9 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) struct sk_buff *frag_iter; int i, copy; + /* Copies user data */ + lazy_clear_cpu_interrupt(); + if (offset > (int)skb->len - len) goto fault; @@ -2467,6 +2487,9 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, struct sk_buff *frag_iter; int pos = 0; + /* Reads packet data */ + lazy_clear_cpu_interrupt(); + /* Checksum header. */ if (copy > 0) { if (copy > len) @@ -2559,6 +2582,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, struct sk_buff *frag_iter; int pos = 0; + /* Reads packet data */ + lazy_clear_cpu_interrupt(); + /* Copy header. */ if (copy > 0) { if (copy > len) -- 2.17.2