diff options
Diffstat (limited to 'contrib/coverity/model.c')
-rw-r--r-- | contrib/coverity/model.c | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/contrib/coverity/model.c b/contrib/coverity/model.c new file mode 100644 index 000000000000..8b4d14ee22a2 --- /dev/null +++ b/contrib/coverity/model.c @@ -0,0 +1,654 @@ +/* + * Coverity Scan model + * https://scan.coverity.com/models + * + * This is a modeling file for Coverity Scan. + * Modeling helps to avoid false positives. + * + * - Modeling doesn't need full structs and typedefs. Rudimentary structs + * and similar types are sufficient. + * - An uninitialized local pointer is not an error. It signifies that the + * variable could be either NULL or have some data. + * + * Coverity Scan doesn't pick up modifications automatically. The model file + * must be uploaded by an admin in the analysis settings. + * + * Some of this initially cribbed from: + * + * https://github.com/kees/coverity-linux/blob/trunk/model.c + * + * The below model was based on the original model by Brian Behlendorf for the + * original zfsonlinux/zfs repository. Some inspiration was taken from + * kees/coverity-linux, specifically involving memory copies. + */ + +#include <stdarg.h> + +#define KM_NOSLEEP 0x0001 /* cannot block for memory; may fail */ + +#define UMEM_DEFAULT 0x0000 /* normal -- may fail */ +#define UMEM_NOFAIL 0x0100 /* Never fails */ + +#define NULL (0) + +typedef enum { + B_FALSE = 0, + B_TRUE = 1 +} boolean_t; + +typedef unsigned int uint_t; + +int condition0, condition1; + +int +ddi_copyin(const void *from, void *to, size_t len, int flags) +{ + (void) flags; + __coverity_negative_sink__(len); + __coverity_tainted_data_argument__(from); + __coverity_tainted_data_argument__(to); + __coverity_writeall__(to); +} + +void * +memset(void *dst, int c, size_t len) +{ + __coverity_negative_sink__(len); + if (c == 0) + __coverity_writeall0__(dst); + else + __coverity_writeall__(dst); + return (dst); +} + +void * +memmove(void *dst, void *src, size_t len) +{ + int first = ((char *)src)[0]; + int last = ((char *)src)[len-1]; + + __coverity_negative_sink__(len); + __coverity_writeall__(dst); + return (dst); +} + +void * +memcpy(void *dst, void *src, size_t len) +{ + int first = ((char *)src)[0]; + int last = ((char *)src)[len-1]; + + __coverity_negative_sink__(len); + __coverity_writeall__(dst); + return (dst); +} + +void * +umem_alloc_aligned(size_t size, size_t align, int kmflags) +{ + __coverity_negative_sink__(size); + __coverity_negative_sink__(align); + + if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) { + void *buf = __coverity_alloc__(size); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "umem_free"); + return (buf); + } + + return (NULL); +} + +void * +umem_alloc(size_t size, int kmflags) +{ + __coverity_negative_sink__(size); + + if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) { + void *buf = __coverity_alloc__(size); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "umem_free"); + return (buf); + } + + return (NULL); +} + +void * +umem_zalloc(size_t size, int kmflags) +{ + __coverity_negative_sink__(size); + + if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) { + void *buf = __coverity_alloc__(size); + __coverity_writeall0__(buf); + __coverity_mark_as_afm_allocated__(buf, "umem_free"); + return (buf); + } + + return (NULL); +} + +void +umem_free(void *buf, size_t size) +{ + __coverity_negative_sink__(size); + __coverity_free__(buf); +} + +typedef struct {} umem_cache_t; + +void * +umem_cache_alloc(umem_cache_t *skc, int flags) +{ + (void) skc; + + if (condition1) + __coverity_sleep__(); + + if (((UMEM_NOFAIL & flags) == UMEM_NOFAIL) || condition0) { + void *buf = __coverity_alloc_nosize__(); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "umem_cache_free"); + return (buf); + } + + return (NULL); +} + +void +umem_cache_free(umem_cache_t *skc, void *obj) +{ + (void) skc; + + __coverity_free__(obj); +} + +void * +spl_kmem_alloc(size_t sz, int fl, const char *func, int line) +{ + (void) func; + (void) line; + + __coverity_negative_sink__(sz); + + if (condition1) + __coverity_sleep__(); + + if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) { + void *buf = __coverity_alloc__(sz); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "spl_kmem_free"); + return (buf); + } + + return (NULL); +} + +void * +spl_kmem_zalloc(size_t sz, int fl, const char *func, int line) +{ + (void) func; + (void) line; + + __coverity_negative_sink__(sz); + + if (condition1) + __coverity_sleep__(); + + if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) { + void *buf = __coverity_alloc__(sz); + __coverity_writeall0__(buf); + __coverity_mark_as_afm_allocated__(buf, "spl_kmem_free"); + return (buf); + } + + return (NULL); +} + +void +spl_kmem_free(const void *ptr, size_t sz) +{ + __coverity_negative_sink__(sz); + __coverity_free__(ptr); +} + +char * +kmem_vasprintf(const char *fmt, va_list ap) +{ + char *buf = __coverity_alloc_nosize__(); + (void) ap; + + __coverity_string_null_sink__(fmt); + __coverity_string_size_sink__(fmt); + + __coverity_writeall__(buf); + + __coverity_mark_as_afm_allocated__(buf, "kmem_strfree"); + + return (buf); +} + +char * +kmem_asprintf(const char *fmt, ...) +{ + char *buf = __coverity_alloc_nosize__(); + + __coverity_string_null_sink__(fmt); + __coverity_string_size_sink__(fmt); + + __coverity_writeall__(buf); + + __coverity_mark_as_afm_allocated__(buf, "kmem_strfree"); + + return (buf); +} + +char * +kmem_strdup(const char *str) +{ + char *buf = __coverity_alloc_nosize__(); + + __coverity_string_null_sink__(str); + __coverity_string_size_sink__(str); + + __coverity_writeall__(buf); + + __coverity_mark_as_afm_allocated__(buf, "kmem_strfree"); + + return (buf); + + +} + +void +kmem_strfree(char *str) +{ + __coverity_free__(str); +} + +void * +spl_vmem_alloc(size_t sz, int fl, const char *func, int line) +{ + (void) func; + (void) line; + + __coverity_negative_sink__(sz); + + if (condition1) + __coverity_sleep__(); + + if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) { + void *buf = __coverity_alloc__(sz); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "spl_vmem_free"); + return (buf); + } + + return (NULL); +} + +void * +spl_vmem_zalloc(size_t sz, int fl, const char *func, int line) +{ + (void) func; + (void) line; + + if (condition1) + __coverity_sleep__(); + + if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) { + void *buf = __coverity_alloc__(sz); + __coverity_writeall0__(buf); + __coverity_mark_as_afm_allocated__(buf, "spl_vmem_free"); + return (buf); + } + + return (NULL); +} + +void +spl_vmem_free(const void *ptr, size_t sz) +{ + __coverity_negative_sink__(sz); + __coverity_free__(ptr); +} + +typedef struct {} spl_kmem_cache_t; + +void * +spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags) +{ + (void) skc; + + if (condition1) + __coverity_sleep__(); + + if ((flags == 0) || condition0) { + void *buf = __coverity_alloc_nosize__(); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "spl_kmem_cache_free"); + return (buf); + } +} + +void +spl_kmem_cache_free(spl_kmem_cache_t *skc, void *obj) +{ + (void) skc; + + __coverity_free__(obj); +} + +typedef struct {} zfsvfs_t; + +int +zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp) +{ + (void) osname; + (void) readonly; + + if (condition1) + __coverity_sleep__(); + + if (condition0) { + *zfvp = __coverity_alloc_nosize__(); + __coverity_writeall__(*zfvp); + return (0); + } + + return (1); +} + +void +zfsvfs_free(zfsvfs_t *zfsvfs) +{ + __coverity_free__(zfsvfs); +} + +typedef struct {} nvlist_t; + +int +nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag) +{ + (void) nvflag; + + if (condition1) + __coverity_sleep__(); + + if ((kmflag == 0) || condition0) { + *nvlp = __coverity_alloc_nosize__(); + __coverity_mark_as_afm_allocated__(*nvlp, "nvlist_free"); + __coverity_writeall__(*nvlp); + return (0); + } + + return (-1); + +} + +int +nvlist_dup(const nvlist_t *nvl, nvlist_t **nvlp, int kmflag) +{ + nvlist_t read = *nvl; + + if (condition1) + __coverity_sleep__(); + + if ((kmflag == 0) || condition0) { + nvlist_t *nvl = __coverity_alloc_nosize__(); + __coverity_mark_as_afm_allocated__(nvl, "nvlist_free"); + __coverity_writeall__(nvl); + *nvlp = nvl; + return (0); + } + + return (-1); +} + +void +nvlist_free(nvlist_t *nvl) +{ + __coverity_free__(nvl); +} + +int +nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, + int kmflag) +{ + (void) nvl; + (void) encoding; + + if (*bufp == NULL) { + if (condition1) + __coverity_sleep__(); + + if ((kmflag == 0) || condition0) { + char *buf = __coverity_alloc_nosize__(); + __coverity_writeall__(buf); + /* + * We cannot use __coverity_mark_as_afm_allocated__() + * because the free function varies between the kernel + * and userspace. + */ + *bufp = buf; + return (0); + } + + return (-1); + } + + /* + * Unfortunately, errors from the buffer being too small are not + * possible to model, so we assume success. + */ + __coverity_negative_sink__(*buflen); + __coverity_writeall__(*bufp); + return (0); +} + + +int +nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag) +{ + __coverity_negative_sink__(buflen); + + if (condition1) + __coverity_sleep__(); + + if ((kmflag == 0) || condition0) { + nvlist_t *nvl = __coverity_alloc_nosize__(); + __coverity_mark_as_afm_allocated__(nvl, "nvlist_free"); + __coverity_writeall__(nvl); + *nvlp = nvl; + int first = buf[0]; + int last = buf[buflen-1]; + return (0); + } + + return (-1); + +} + +void * +malloc(size_t size) +{ + void *buf = __coverity_alloc__(size); + + if (condition1) + __coverity_sleep__(); + + __coverity_negative_sink__(size); + __coverity_mark_as_uninitialized_buffer__(buf); + __coverity_mark_as_afm_allocated__(buf, "free"); + + return (buf); +} + +void * +calloc(size_t nmemb, size_t size) +{ + void *buf = __coverity_alloc__(size * nmemb); + + if (condition1) + __coverity_sleep__(); + + __coverity_negative_sink__(size); + __coverity_writeall0__(buf); + __coverity_mark_as_afm_allocated__(buf, "free"); + return (buf); +} +void +free(void *buf) +{ + __coverity_free__(buf); +} + +int +sched_yield(void) +{ + __coverity_sleep__(); +} + +typedef struct {} kmutex_t; +typedef struct {} krwlock_t; +typedef int krw_t; + +/* + * Coverty reportedly does not support macros, so this only works for + * userspace. + */ + +void +mutex_enter(kmutex_t *mp) +{ + if (condition0) + __coverity_sleep__(); + + __coverity_exclusive_lock_acquire__(mp); +} + +int +mutex_tryenter(kmutex_t *mp) +{ + if (condition0) { + __coverity_exclusive_lock_acquire__(mp); + return (1); + } + + return (0); +} + +void +mutex_exit(kmutex_t *mp) +{ + __coverity_exclusive_lock_release__(mp); +} + +void +rw_enter(krwlock_t *rwlp, krw_t rw) +{ + (void) rw; + + if (condition0) + __coverity_sleep__(); + + __coverity_recursive_lock_acquire__(rwlp); +} + +void +rw_exit(krwlock_t *rwlp) +{ + __coverity_recursive_lock_release__(rwlp); + +} + +int +rw_tryenter(krwlock_t *rwlp, krw_t rw) +{ + if (condition0) { + __coverity_recursive_lock_acquire__(rwlp); + return (1); + } + + return (0); +} + +/* Thus, we fallback to the Linux kernel locks */ +struct {} mutex; +struct {} rw_semaphore; + +void +mutex_lock(struct mutex *lock) +{ + if (condition0) { + __coverity_sleep__(); + } + __coverity_exclusive_lock_acquire__(lock); +} + +void +mutex_unlock(struct mutex *lock) +{ + __coverity_exclusive_lock_release__(lock); +} + +void +down_read(struct rw_semaphore *sem) +{ + if (condition0) { + __coverity_sleep__(); + } + __coverity_recursive_lock_acquire__(sem); +} + +void +down_write(struct rw_semaphore *sem) +{ + if (condition0) { + __coverity_sleep__(); + } + __coverity_recursive_lock_acquire__(sem); +} + +int +down_read_trylock(struct rw_semaphore *sem) +{ + if (condition0) { + __coverity_recursive_lock_acquire__(sem); + return (1); + } + + return (0); +} + +int +down_write_trylock(struct rw_semaphore *sem) +{ + if (condition0) { + __coverity_recursive_lock_acquire__(sem); + return (1); + } + + return (0); +} + +void +up_read(struct rw_semaphore *sem) +{ + __coverity_recursive_lock_release__(sem); +} + +void +up_write(struct rw_semaphore *sem) +{ + __coverity_recursive_lock_release__(sem); +} + +int +__cond_resched(void) +{ + if (condition0) { + __coverity_sleep__(); + } +} |