lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Thu, 04 Nov 2010 09:54:53 +1100 From: Andrew Hendry <andrew.hendry@...il.com> To: Dan Rosenberg <drosenberg@...curity.com> Cc: netdev@...r.kernel.org, security@...nel.org, stable@...nel.org Subject: Re: [SECURITY] memory corruption in X.25 facilities parsing On Wed, 2010-11-03 at 12:12 +1100, Andrew Hendry wrote: > There is an issue here, under select scenarios I can crash systems. > However the patch doesn't resolve it fully, I think after breaking at > that point the len and p pointers are messed up before it tries to > parse the next facility. > > Maybe it should return not break? It should reject/clear such calls. > I'll start checking if the callers properly handle errors. > Also should it be if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1), > because it does the memcpy with p[1] -1 > > > On Wed, Nov 3, 2010 at 2:02 AM, Dan Rosenberg <drosenberg@...curity.com> wrote: > > I put this together after a quick glance, so if someone knows this code > > better than I do (i.e. at all), feel free to comment or drop this patch > > if it's unnecessary. > > > > A value of 0 will cause a memcpy() of ULONG_MAX size, destroying the > > kernel heap. > > > > Signed-off-by: Dan Rosenberg <drosenberg@...curity.com> > > > > --- linux-2.6.36-rc6.orig/net/x25/x25_facilities.c 2010-09-28 21:01:22.000000000 -0400 > > +++ linux-2.6.36-rc6/net/x25/x25_facilities.c 2010-11-02 10:36:02.827291324 -0400 > > @@ -134,14 +134,14 @@ int x25_parse_facilities(struct sk_buff > > case X25_FAC_CLASS_D: > > switch (*p) { > > case X25_FAC_CALLING_AE: > > - if (p[1] > X25_MAX_DTE_FACIL_LEN) > > + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] == 0) > > break; > > dte_facs->calling_len = p[2]; > > memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); > > *vc_fac_mask |= X25_MASK_CALLING_AE; > > break; > > case X25_FAC_CALLED_AE: > > - if (p[1] > X25_MAX_DTE_FACIL_LEN) > > + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] == 0) > > break; > > dte_facs->called_len = p[2]; > > memcpy(dte_facs->called_ae, &p[3], p[1] - 1); > > > > > > How does this look? It appears to fix it for the cases I could test. Signed-of-by: Andrew Hendry <andrew.hendry@...il.com> diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 771bab0..3a8c4c4 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -134,15 +134,15 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, case X25_FAC_CLASS_D: switch (*p) { case X25_FAC_CALLING_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->calling_len = p[2]; memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLING_AE; break; case X25_FAC_CALLED_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->called_len = p[2]; memcpy(dte_facs->called_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLED_AE; diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 6317896..1d80e10 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -119,6 +119,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp &x25->vc_facil_mask); if (len > 0) skb_pull(skb, len); + else + return -1; /* * Copy any Call User Data. */ -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists