/* * 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 #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__(); } }