From: Eric Dumazet <eric.dumazet@gmail.com>
To: Changli Gao <xiaosuo@gmail.com>
Cc: David Miller <davem@davemloft.net>,
hagen@jauu.net, wirelesser@gmail.com, netdev@vger.kernel.org,
Dan Rosenberg <drosenberg@vsecurity.com>
Subject: Re: [PATCH net-next-2.6] filter: add a security check at install time
Date: Thu, 02 Dec 2010 07:46:24 +0100 [thread overview]
Message-ID: <1291272384.2856.1074.camel@edumazet-laptop> (raw)
In-Reply-To: <AANLkTikK=dy6U0QBjkJxZXeqYXVHwZqjmRhnmYBH-22r@mail.gmail.com>
Le jeudi 02 décembre 2010 à 10:30 +0800, Changli Gao a écrit :
> It seems wrong. Think about the following instructions:
>
> /* m[1] isn't set */
> jeq jt jf
> jt:
> st m[1]
> jmp ja
> jf:
> jmp ja2 /* m[1] is invalidated by masks */
> ja:
> ld m[1] /* -EINVAL is returned */
> ja2:
>
> So you need to search all the possible branches to validate the instructions.
Well, I already did this branch search.
Its only that the instruction following a JMP should not inherit
memvalid from the JMP itself, but the AND of memvalid of all possible
jumps that can arrive to this instruction.
I'll think about it after some coffee, but I feel I might just set
memvalid to ~0 after the JMPS
Thanks
[PATCH v2 net-next-2.6] filter: add a security check at install time
We added some security checks in commit 57fe93b374a6
(filter: make sure filters dont read uninitialized memory) to close a
potential leak of kernel information to user.
This added a potential extra cost at run time, while we can perform a
check of the filter itself, to make sure a malicious user doesnt try to
abuse us.
This patch adds a check_loads() function, whole unique purpose is to
make this check, allocating a temporary array of mask. We scan the
filter and propagate a bitmask information, telling us if a load M(K) is
allowed because a previous store M(K) is guaranteed. (So that
sk_run_filter() can possibly not read unitialized memory)
Note: this can uncover application bug, denying a filter attach,
previously allowed.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Dan Rosenberg <drosenberg@vsecurity.com>
Cc: Changli Gao <xiaosuo@gmail.com>
---
v2: set memvalid to ~0 on JMP instructions
diff --git a/net/core/filter.c b/net/core/filter.c
index a44d27f..0d636ef 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -166,11 +166,9 @@ unsigned int sk_run_filter(struct sk_buff *skb, const struct sock_filter *fentry
u32 A = 0; /* Accumulator */
u32 X = 0; /* Index Register */
u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */
- unsigned long memvalid = 0;
u32 tmp;
int k;
- BUILD_BUG_ON(BPF_MEMWORDS > BITS_PER_LONG);
/*
* Process array of filter instructions.
*/
@@ -318,12 +316,10 @@ load_b:
X = K;
continue;
case BPF_S_LD_MEM:
- A = (memvalid & (1UL << K)) ?
- mem[K] : 0;
+ A = mem[K];
continue;
case BPF_S_LDX_MEM:
- X = (memvalid & (1UL << K)) ?
- mem[K] : 0;
+ X = mem[K];
continue;
case BPF_S_MISC_TAX:
X = A;
@@ -336,11 +332,9 @@ load_b:
case BPF_S_RET_A:
return A;
case BPF_S_ST:
- memvalid |= 1UL << K;
mem[K] = A;
continue;
case BPF_S_STX:
- memvalid |= 1UL << K;
mem[K] = X;
continue;
default:
@@ -419,6 +413,66 @@ load_b:
}
EXPORT_SYMBOL(sk_run_filter);
+/*
+ * Security :
+ * A BPF program is able to use 16 cells of memory to store intermediate
+ * values (check u32 mem[BPF_MEMWORDS] in sk_run_filter())
+ * As we dont want to clear mem[] array for each packet going through
+ * sk_run_filter(), we check that filter loaded by user never try to read
+ * a cell if not previously written, and we check all branches to be sure
+ * a malicious user doesnt try to abuse us.
+ */
+static int check_load_and_stores(struct sock_filter *filter, int flen)
+{
+ u16 *masks, memvalid = 0; /* one bit per cell, 16 cells */
+ int pc, ret = 0;
+
+ BUILD_BUG_ON(BPF_MEMWORDS > 16);
+ masks = kmalloc(flen * sizeof(*masks), GFP_KERNEL);
+ if (!masks)
+ return -ENOMEM;
+ memset(masks, 0xff, flen * sizeof(*masks));
+
+ for (pc = 0; pc < flen; pc++) {
+ memvalid &= masks[pc];
+
+ switch (filter[pc].code) {
+ case BPF_S_ST:
+ case BPF_S_STX:
+ memvalid |= (1 << filter[pc].k);
+ break;
+ case BPF_S_LD_MEM:
+ case BPF_S_LDX_MEM:
+ if (!(memvalid & (1 << filter[pc].k))) {
+ ret = -EINVAL;
+ goto error;
+ }
+ break;
+ case BPF_S_JMP_JA:
+ /* a jump must set masks on target */
+ masks[pc + 1 + filter[pc].k] &= memvalid;
+ memvalid = ~0;
+ break;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JEQ_X:
+ case BPF_S_JMP_JGE_K:
+ case BPF_S_JMP_JGE_X:
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGT_X:
+ case BPF_S_JMP_JSET_X:
+ case BPF_S_JMP_JSET_K:
+ /* a jump must set masks on targets */
+ masks[pc + 1 + filter[pc].jt] &= memvalid;
+ masks[pc + 1 + filter[pc].jf] &= memvalid;
+ memvalid = ~0;
+ break;
+ }
+ }
+error:
+ kfree(masks);
+ return ret;
+}
+
/**
* sk_chk_filter - verify socket filter code
* @filter: filter to verify
@@ -547,7 +601,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
switch (filter[flen - 1].code) {
case BPF_S_RET_K:
case BPF_S_RET_A:
- return 0;
+ return check_load_and_stores(filter, flen);
}
return -EINVAL;
}
next prev parent reply other threads:[~2010-12-02 6:46 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-30 9:22 multi bpf filter will impact performance? Rui
2010-11-30 9:34 ` Eric Dumazet
[not found] ` <AANLkTi=VpmnrXTBNV7McQm6mq9ULT7KTKbM8_hLPoL=2@mail.gmail.com>
[not found] ` <1291127670.2904.96.camel@edumazet-laptop>
2010-12-01 3:48 ` Rui
2010-12-01 4:03 ` Eric Dumazet
2010-12-01 7:45 ` [PATCH net-next-2.6] filter: add SKF_AD_RXHASH and SKF_AD_CPU Eric Dumazet
2010-12-01 8:03 ` Changli Gao
2010-12-06 21:02 ` David Miller
2010-12-03 9:40 ` multi bpf filter will impact performance? Junchang Wang
2010-12-01 7:36 ` Changli Gao
2010-12-01 7:47 ` Eric Dumazet
2010-12-01 7:59 ` Changli Gao
2010-12-01 8:09 ` Eric Dumazet
2010-12-01 8:15 ` Changli Gao
2010-12-01 8:42 ` Eric Dumazet
2010-12-01 17:22 ` Hagen Paul Pfeifer
2010-12-01 18:18 ` David Miller
2010-12-01 18:24 ` David Miller
2010-12-01 18:24 ` Eric Dumazet
2010-12-01 18:44 ` David Miller
2010-12-01 19:48 ` Eric Dumazet
2010-12-01 20:23 ` David Miller
2010-12-01 20:45 ` [PATCH net-next-2.6] filter: add a security check at install time Eric Dumazet
2010-12-02 2:30 ` Changli Gao
2010-12-02 6:46 ` Eric Dumazet [this message]
2010-12-02 8:11 ` Changli Gao
2010-12-02 8:53 ` Eric Dumazet
2010-12-02 9:00 ` Eric Dumazet
2010-12-02 9:10 ` Changli Gao
2010-12-02 9:54 ` Eric Dumazet
2010-12-02 10:10 ` Changli Gao
2010-12-02 11:15 ` Eric Dumazet
2010-12-02 11:29 ` Changli Gao
2010-12-02 13:14 ` Eric Dumazet
2010-12-02 10:59 ` Changli Gao
2010-12-06 21:07 ` David Miller
2010-12-03 6:32 ` multi bpf filter will impact performance? Eric Dumazet
2010-12-05 20:53 ` PATCH] filter: fix sk_filter rcu handling Eric Dumazet
2010-12-05 21:08 ` Andi Kleen
2010-12-05 21:28 ` Eric Dumazet
2010-12-06 17:29 ` David Miller
2010-11-30 10:01 ` multi bpf filter will impact performance? Eric Dumazet
2010-11-30 11:17 ` Eric Dumazet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1291272384.2856.1074.camel@edumazet-laptop \
--to=eric.dumazet@gmail.com \
--cc=davem@davemloft.net \
--cc=drosenberg@vsecurity.com \
--cc=hagen@jauu.net \
--cc=netdev@vger.kernel.org \
--cc=wirelesser@gmail.com \
--cc=xiaosuo@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox