linux
Debugging code may derefence a NULL pointer
Pointer `dst' may be NULL and, if SCTP_DEBUG_PRINTK is enabled, is dereferenced by a call to printk.
Bug fixed by commit ee3f34e8572
| Type | NullDereference |
| Config | "IP_SCTP && IPV6 && SCTP_DBG_MSG" (3rd degree) |
| C-features | PointerAliasing |
| Fix-in | code |
| Location | net/sctp/ |
#include <stdbool.h>
#include <stdlib.h>
#ifndef SCTP_DEBUG
#ifdef CONFIG_SCTP_DBG_MSG
#define SCTP_DEBUG 1
#else
#define SCTP_DEBUG 0
#endif /* CONFIG_SCTP_DBG */
#endif /* SCTP_DEBUG */
bool IS_ERR(const void *ptr)
{
return (ptr == (void *)-1);
}
bool IS_ERR_OR_NULL(const void *ptr)
{
return !ptr || IS_ERR(ptr);
}
#if SCTP_DEBUG
#define SCTP_DEBUG_PRINTK(ptr) ((*ptr)++)
#else
#define SCTP_DEBUG_PRINTK(ptr)
#endif
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
static int some_int = 1;
int *ip6_dst_lookup_flow()
{
return &some_int;
}
void sctp_v6_get_dst()
{
int *dst = NULL;
dst = ip6_dst_lookup_flow();
if (!IS_ERR(dst)) {
dst = NULL; // (2)
}
if (!IS_ERR(dst)) {
char *rt =(char *) dst; // (3)
SCTP_DEBUG_PRINTK(rt); // (4) ERROR
}
}
#endif
int main()
{
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
sctp_v6_get_dst(); // (1)
#endif
return 0;
}
diff --git a/simple/ee3f34e.c b/simple/ee3f34e.c
--- a/simple/ee3f34e.c
+++ b/simple/ee3f34e.c
@@ -41,7 +41,7 @@
if (!IS_ERR(dst)) {
dst = NULL;
}
- if (!IS_ERR(dst)) {
+ if (!IS_ERR_OR_NULL(dst)) {
char *rt =(char *) dst;
SCTP_DEBUG_PRINTK(rt); // ERROR
}
#include <stdbool.h>
#include <stdlib.h>
#ifndef SCTP_DEBUG
#ifdef CONFIG_SCTP_DBG_MSG
#define SCTP_DEBUG 1
#else
#define SCTP_DEBUG 0
#endif /* CONFIG_SCTP_DBG */
#endif /* SCTP_DEBUG */
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
static int some_int = 1;
#endif
int main()
{
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
// sctp_v6_get_dst();
int *dst = NULL;
dst = &some_int;
if (!(dst == (void *)-1)) {
dst = NULL;
}
if (!(dst == (void *)-1)) {
char *rt =(char *) dst;
// SCTP_DEBUG_PRINTK(rt); // ERROR
#if SCTP_DEBUG
((*rt)++);
#else
#endif
}
#endif
return 0;
}
. call net/sctp/ipv6.c:257:sctp_v6_get_dst()
. 265: union sctp_addr *baddr = NULL;
. 290: dst = ip6_dst_lookup_flow(sk, fl6, NULL, false);
. 299: if (!IS_ERR(dst))
. 321: dst = NULL;
// somehow `baddr' is still pointing to NULL
// or maybe `dst' becomes NULL at 344
. 348: if (!IS_ERR(dst))
. 350: rt = (struct rt6_info *)dst;
// `rt' is an alias for `dst'
. [SCTP_DBG_MSG] 352: SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n",
. ERROR 353: &rt->rt6i_dst.addr, &fl6->saddr);