| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // Licensed under BSD-MIT: See LICENSE.
- #ifndef CCAN_PTR_VALID_H
- #define CCAN_PTR_VALID_H
- #include "config.h"
- #include <stdbool.h>
- #include <stdlib.h>
- /**
- * ptr_valid_read - can I safely read from a pointer?
- * @p: the proposed pointer.
- *
- * This function verifies that the pointer @p is safe to dereference for
- * reading. It is very slow, particularly if the answer is "no".
- *
- * Sets errno to EFAULT on failure.
- *
- * See Also:
- * ptr_valid_batch_read()
- */
- #define ptr_valid_read(p) \
- ptr_valid_r((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
- /**
- * ptr_valid_write - can I safely write to a pointer?
- * @p: the proposed pointer.
- *
- * This function verifies that the pointer @p is safe to dereference
- * for writing (and reading). It is very slow, particularly if the
- * answer is "no".
- *
- * Sets errno to EFAULT on failure.
- *
- * See Also:
- * ptr_valid_batch_write()
- */
- #define ptr_valid_write(p) \
- ptr_valid_w((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
- /**
- * ptr_valid_string - can I safely read a string?
- * @p: the proposed string.
- *
- * This function verifies that the pointer @p is safe to dereference
- * up to a nul character. It is very slow, particularly if the answer
- * is "no".
- *
- * Sets errno to EFAULT on failure.
- *
- * See Also:
- * ptr_valid_batch_string()
- */
- bool ptr_valid_string(const char *p);
- /**
- * ptr_valid - generic pointer check function
- * @p: the proposed pointer.
- * @align: the alignment requirements of the pointer.
- * @size: the size of the region @p should point to
- * @write: true if @p should be writable as well as readable.
- *
- * This function verifies that the pointer @p is safe to dereference.
- * It is very slow, particularly if the answer is "no".
- *
- * Sets errno to EFAULT on failure.
- *
- * See Also:
- * ptr_valid_batch()
- */
- bool ptr_valid(const void *p, size_t align, size_t size, bool write);
- /**
- * struct ptr_valid_batch - pointer to store state for batch ptr ops
- *
- * Treat as private.
- */
- struct ptr_valid_batch {
- unsigned int num_maps;
- struct ptr_valid_map *maps;
- int child_pid;
- int to_child, from_child;
- void *last;
- bool last_ok;
- };
- /**
- * ptr_valid_batch_start - prepare for a batch of ptr_valid checks.
- * @batch: an uninitialized ptr_valid_batch structure.
- *
- * This initializes @batch; this same @batch pointer can be reused
- * until the memory map changes (eg. via mmap(), munmap() or even
- * malloc() and free()).
- *
- * This is useful to check many pointers, because otherwise it can be
- * extremely slow.
- *
- * Example:
- * struct linked {
- * struct linked *next;
- * const char *str;
- * };
- *
- * static bool check_linked_carefully(struct linked *head)
- * {
- * struct ptr_valid_batch batch;
- * struct linked *old = head;
- * bool half = true;
- *
- * // If this fails, we can't check. Assume OK.
- * if (!ptr_valid_batch_start(&batch))
- * return true;
- *
- * while (head) {
- * if (!ptr_valid_batch_read(&batch, head))
- * goto fail;
- * if (!ptr_valid_batch_string(&batch, head->str))
- * goto fail;
- * // Loop detection; move old at half speed of head.
- * if (half)
- * old = old->next;
- * half = !half;
- * if (head == old) {
- * errno = ELOOP;
- * goto fail;
- * }
- * }
- * ptr_valid_batch_end(&batch);
- * return true;
- *
- * fail:
- * ptr_valid_batch_end(&batch);
- * return false;
- * }
- *
- * See Also:
- * ptr_valid_batch_stop()
- */
- bool ptr_valid_batch_start(struct ptr_valid_batch *batch);
- /**
- * ptr_valid_batch_read - can I safely read from a pointer?
- * @batch: the batch initialized by ptr_valid_batch_start().
- * @p: the proposed pointer.
- *
- * Batched version of ptr_valid_read().
- */
- #define ptr_valid_batch_read(batch, p) \
- ptr_valid_batch_r((batch), \
- (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
- /**
- * ptr_valid_batch_write - can I safely write to a pointer?
- * @batch: the batch initialized by ptr_valid_batch_start().
- * @p: the proposed pointer.
- *
- * Batched version of ptr_valid_write().
- */
- #define ptr_valid_batch_write(batch, p) \
- ptr_valid_batch_w((batch), \
- (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
- /**
- * ptr_valid_batch_string - can I safely read a string?
- * @batch: the batch initialized by ptr_valid_batch_start().
- * @p: the proposed string.
- *
- * Batched version of ptr_valid_string().
- */
- bool ptr_valid_batch_string(struct ptr_valid_batch *batch, const char *p);
- /**
- * ptr_valid_batch - generic batched pointer check function
- * @batch: the batch initialized by ptr_valid_batch_start().
- * @p: the proposed pointer.
- * @align: the alignment requirements of the pointer.
- * @size: the size of the region @p should point to
- * @write: true if @p should be writable as well as readable.
- *
- * Batched version of ptr_valid().
- */
- bool ptr_valid_batch(struct ptr_valid_batch *batch,
- const void *p, size_t alignment, size_t size, bool write);
- /**
- * ptr_valid_batch_end - end a batch of ptr_valid checks.
- * @batch: a ptr_valid_batch structure.
- *
- * This is used after all checks are complete.
- *
- * See Also:
- * ptr_valid_batch_start()
- */
- void ptr_valid_batch_end(struct ptr_valid_batch *batch);
- /* These wrappers get constness correct. */
- static inline bool ptr_valid_r(const void *p, size_t align, size_t size)
- {
- return ptr_valid(p, align, size, false);
- }
- static inline bool ptr_valid_w(void *p, size_t align, size_t size)
- {
- return ptr_valid(p, align, size, true);
- }
- static inline bool ptr_valid_batch_r(struct ptr_valid_batch *batch,
- const void *p, size_t align, size_t size)
- {
- return ptr_valid_batch(batch, p, align, size, false);
- }
- static inline bool ptr_valid_batch_w(struct ptr_valid_batch *batch,
- void *p, size_t align, size_t size)
- {
- return ptr_valid_batch(batch, p, align, size, true);
- }
- struct ptr_valid_map {
- const char *start, *end;
- bool is_write;
- };
- #if HAVE_ALIGNOF
- #define PTR_VALID_ALIGNOF(var) __alignof__(var)
- #else
- /* Can't check this... */
- #define PTR_VALID_ALIGNOF(var) 1
- #endif
- #endif /* CCAN_PTR_VALID_H */
|