aboutsummaryrefslogtreecommitdiff
path: root/contrib/coverity/model.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/coverity/model.c')
-rw-r--r--contrib/coverity/model.c654
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__();
+ }
+}