Skip to content

Instantly share code, notes, and snippets.

@sbahra
Created April 22, 2019 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbahra/5c4a9217c7b7ba9be799b02637729da9 to your computer and use it in GitHub Desktop.
Save sbahra/5c4a9217c7b7ba9be799b02637729da9 to your computer and use it in GitHub Desktop.
{
/*
* For now, there will be two types of checks: individual and combinative.
* Individual checks are run on each argument specified in the positions array.
* Combinative checks are run once on all arguments specified in the positions
* array and have some implicit operator associated with them (e.g., overflow
* may imply addition).
*
* Available checks:
* valid_memory_size - individual
* - annotates a size parameter if it exceeds available memory
* valid_heap_address - individual
* - annotates if an address is not returned by malloc/realloc
* or is currently in free state
* buffer_overflow - combinative
* - annotates a buffer or length parameter if their
* combination results in an invalid memory reference.
* This check supports exactly two arguments. The first
* argument position must be the location of a buffer
* parameter; the second argument position must
* be the location of the length parameter.
* readable, writable, - individual
* executable annotates the specified reference parameter if it does
* not have the specified permissions or is not accessible.
*
* Qualifiers modify how or if an argument checker performs its action on the specified
* arguments.
*
* Available qualifiers:
* null - For checks that recognize this qualifier (currently readable,
* writable and executable), the entire check will be skipped
* if the argument resolves to NULL.
*/
"rules": [
/* libevent */
{
"function": "^(evhttp_(bind|accept)_socket*)|(evbuffer_(free|lock|unlock|pullup|(un)?freeze|get_length|get_contiguous_space|expand|drain|write(_atmost)?|read(ln)?|add_(v)?printf|(reserve|commit)_space)$)|(bufferevent_(free|get_(input|output|base|priority|enabled)+|trigger_nolock_|enable|disable|(un)?lock|flush|trigger(_event)?)$)",
"object": "^libevent*",
"arguments": [
{
"positions": [0],
"checks": ["readable", "writable"]
}
],
"classifier": "libevent"
},
{
"function": "^(evbuffer_(((add|remove)_buffer)|prepend(_buffer)?))|(bufferevent_(write_read)(_buffer)?)|(evutil_ascii_str(n)?casecmp)|(evhttp_(get_body|handle_request))$",
"object": "^libevent*",
"arguments": [
{
"positions": [0, 1],
"checks": ["readable", "writable"]
}
],
"classifier": "libevent"
},
/* ASAN */
{
"function": "^(__asan|__sanitizer)",
"classifier": "asan"
},
{
"function": "^evbuffer_(add|remove|copyout)$",
"object": "^libevent*",
"arguments": [
{
"positions": [0, 1],
"checks": ["readable", "writable"]
},
{
"positions": [1, 2],
"qualifiers": ["null"],
"checks": ["buffer_overflow"]
}
],
"classifier": "libevent"
},
{
"function": "^evbuffer_search$",
"object": "^libevent*",
"arguments": [
{
"positions": [0, 1],
"checks": ["readable", "writable"]
},
{
"positions": [3],
"qualifiers": ["null"],
"checks": ["readable", "writable"]
}
],
"classifier": "libevent"
},
{
"function": "^evbuffer_search_range$",
"object": "^libevent*",
"arguments": [
{
"positions": [0, 1],
"checks": ["readable", "writable"]
},
{
"positions": [3, 4],
"qualifiers": ["null"],
"checks": ["readable", "writable"]
}
],
"classifier": "libevent"
},
{
"function": "^evbuffer_peek$",
"object": "^libevent*",
"arguments": [
{
"positions": [0],
"checks": ["readable", "writable"]
},
{
"positions": [2, 3],
"qualifiers": ["null"],
"checks": ["readable", "writable"]
}
],
"classifier": "libevent"
},
/* libc */
{
"function": "^_*(libc)?_*free$",
"object": "libc|jemalloc",
"arguments": [
{
"positions": [0],
"qualifiers": ["null"],
"checks": ["valid_heap_address"]
}
],
"classifier": "invalid-free"
},
{
"function": "^_*(libc)?_*realloc$",
"object": "libc",
"arguments": [
{
"positions": [0],
"qualifiers": ["null"],
"checks": ["valid_heap_address"]
},
{
"positions": [1],
"checks": ["valid_memory_size"]
}
],
"classifier": "malloc"
},
{
"function": "^_*(libc)?_*malloc$",
"arguments": [
{
"positions": [0],
"checks": ["valid_memory_size"]
}
],
"classifier": "malloc"
},
{
"function": "^_*(libc)?_*strcpy$",
"arguments": [
{
"positions": [0],
"checks": ["readable"]
},
{
"positions": [1],
"checks": ["writable"]
}
],
"classifier": "string"
},
{
/*
* Based on initial testing, internal strncpy/memcpy
* implementations expect the length parameter first,
* contrary to their library versions (which expect it
* as the last parameter).
*/
"function": "^_*(libc)?_*(strncpy|memcpy)$",
"arguments": [
{
"positions": [1, 0],
"checks": ["buffer_overflow"]
},
{
"positions": [2, 0],
"checks": ["buffer_overflow"]
},
{
"positions": [1],
"checks": ["readable"]
},
{
"positions": [2],
"checks": ["writable"]
}
],
"classifier": "string"
},
{
/*
* We intentionally don't match internal printf
* functions here; checking the initial printf
* call should be sufficient, and some printf
* matches have different argument orderings
* (e.g. ___printf_chk).
*/
"function": "^printf$",
"arguments": [
{
"positions": [0],
"checks": ["readable"]
}
],
"classifier": "printf"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment