]> git.ozlabs.org Git - ccan/blob - ccan/ptr_valid/ptr_valid.h
crypto/shachain/tools: update to new rbuf API.
[ccan] / ccan / ptr_valid / ptr_valid.h
1 // Licensed under BSD-MIT: See LICENSE.
2 #ifndef CCAN_PTR_VALID_H
3 #define CCAN_PTR_VALID_H
4 #include "config.h"
5 #include <stdbool.h>
6 #include <stdlib.h>
7
8 /**
9  * ptr_valid_read - can I safely read from a pointer?
10  * @p: the proposed pointer.
11  *
12  * This function verifies that the pointer @p is safe to dereference for
13  * reading.  It is very slow, particularly if the answer is "no".
14  *
15  * Sets errno to EFAULT on failure.
16  *
17  * See Also:
18  *      ptr_valid_batch_read()
19  */
20 #define ptr_valid_read(p)                                               \
21         ptr_valid_r((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
22
23 /**
24  * ptr_valid_write - can I safely write to a pointer?
25  * @p: the proposed pointer.
26  *
27  * This function verifies that the pointer @p is safe to dereference
28  * for writing (and reading).  It is very slow, particularly if the
29  * answer is "no".
30  *
31  * Sets errno to EFAULT on failure.
32  *
33  * See Also:
34  *      ptr_valid_batch_write()
35  */
36 #define ptr_valid_write(p)                                              \
37         ptr_valid_w((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
38
39 /**
40  * ptr_valid_string - can I safely read a string?
41  * @p: the proposed string.
42  *
43  * This function verifies that the pointer @p is safe to dereference
44  * up to a nul character.  It is very slow, particularly if the answer
45  * is "no".
46  *
47  * Sets errno to EFAULT on failure.
48  *
49  * See Also:
50  *      ptr_valid_batch_string()
51  */
52 bool ptr_valid_string(const char *p);
53
54 /**
55  * ptr_valid - generic pointer check function
56  * @p: the proposed pointer.
57  * @align: the alignment requirements of the pointer.
58  * @size: the size of the region @p should point to
59  * @write: true if @p should be writable as well as readable.
60  *
61  * This function verifies that the pointer @p is safe to dereference.
62  * It is very slow, particularly if the answer is "no".
63  *
64  * Sets errno to EFAULT on failure.
65  *
66  * See Also:
67  *      ptr_valid_batch()
68  */
69 bool ptr_valid(const void *p, size_t align, size_t size, bool write);
70
71 /**
72  * struct ptr_valid_batch - pointer to store state for batch ptr ops
73  *
74  * Treat as private.
75  */
76 struct ptr_valid_batch {
77         unsigned int num_maps;
78         struct ptr_valid_map *maps;
79         int child_pid;
80         int to_child, from_child;
81         void *last;
82         bool last_ok;
83 };
84
85 /**
86  * ptr_valid_batch_start - prepare for a batch of ptr_valid checks.
87  * @batch: an uninitialized ptr_valid_batch structure.
88  *
89  * This initializes @batch; this same @batch pointer can be reused
90  * until the memory map changes (eg. via mmap(), munmap() or even
91  * malloc() and free()).
92  *
93  * This is useful to check many pointers, because otherwise it can be
94  * extremely slow.
95  *
96  * Example:
97  * struct linked {
98  *      struct linked *next;
99  *      const char *str;
100  * };
101  *
102  * static bool check_linked_carefully(struct linked *head)
103  * {
104  *      struct ptr_valid_batch batch;
105  *      struct linked *old = head;
106  *      bool half = true;
107  *
108  *      // If this fails, we can't check.  Assume OK.
109  *      if (!ptr_valid_batch_start(&batch))
110  *              return true;
111  *
112  *      while (head) {
113  *              if (!ptr_valid_batch_read(&batch, head))
114  *                      goto fail;
115  *              if (!ptr_valid_batch_string(&batch, head->str))
116  *                      goto fail;
117  *              // Loop detection; move old at half speed of head.
118  *              if (half)
119  *                      old = old->next;
120  *              half = !half;
121  *              if (head == old) {
122  *                      errno = ELOOP;
123  *                      goto fail;
124  *              }
125  *      }
126  *      ptr_valid_batch_end(&batch);
127  *      return true;
128  *
129  * fail:
130  *      ptr_valid_batch_end(&batch);
131  *      return false;
132  * }
133  *
134  * See Also:
135  *      ptr_valid_batch_stop()
136  */
137 bool ptr_valid_batch_start(struct ptr_valid_batch *batch);
138
139 /**
140  * ptr_valid_batch_read - can I safely read from a pointer?
141  * @batch: the batch initialized by ptr_valid_batch_start().
142  * @p: the proposed pointer.
143  *
144  * Batched version of ptr_valid_read().
145  */
146 #define ptr_valid_batch_read(batch, p)                                  \
147         ptr_valid_batch_r((batch),                                      \
148                           (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
149
150 /**
151  * ptr_valid_batch_write - can I safely write to a pointer?
152  * @batch: the batch initialized by ptr_valid_batch_start().
153  * @p: the proposed pointer.
154  *
155  * Batched version of ptr_valid_write().
156  */
157 #define ptr_valid_batch_write(batch, p)                                 \
158         ptr_valid_batch_w((batch),                                      \
159                           (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
160
161 /**
162  * ptr_valid_batch_string - can I safely read a string?
163  * @batch: the batch initialized by ptr_valid_batch_start().
164  * @p: the proposed string.
165  *
166  * Batched version of ptr_valid_string().
167  */
168 bool ptr_valid_batch_string(struct ptr_valid_batch *batch, const char *p);
169
170 /**
171  * ptr_valid_batch - generic batched pointer check function
172  * @batch: the batch initialized by ptr_valid_batch_start().
173  * @p: the proposed pointer.
174  * @align: the alignment requirements of the pointer.
175  * @size: the size of the region @p should point to
176  * @write: true if @p should be writable as well as readable.
177  *
178  * Batched version of ptr_valid().
179  */
180 bool ptr_valid_batch(struct ptr_valid_batch *batch,
181                      const void *p, size_t alignment, size_t size, bool write);
182
183 /**
184  * ptr_valid_batch_end - end a batch of ptr_valid checks.
185  * @batch: a ptr_valid_batch structure.
186  *
187  * This is used after all checks are complete.
188  *
189  * See Also:
190  *      ptr_valid_batch_start()
191  */
192 void ptr_valid_batch_end(struct ptr_valid_batch *batch);
193
194
195 /* These wrappers get constness correct. */
196 static inline bool ptr_valid_r(const void *p, size_t align, size_t size)
197 {
198         return ptr_valid(p, align, size, false);
199 }
200
201 static inline bool ptr_valid_w(void *p, size_t align, size_t size)
202 {
203         return ptr_valid(p, align, size, true);
204 }
205
206 static inline bool ptr_valid_batch_r(struct ptr_valid_batch *batch,
207                                      const void *p, size_t align, size_t size)
208 {
209         return ptr_valid_batch(batch, p, align, size, false);
210 }
211
212 static inline bool ptr_valid_batch_w(struct ptr_valid_batch *batch,
213                                      void *p, size_t align, size_t size)
214 {
215         return ptr_valid_batch(batch, p, align, size, true);
216 }
217
218 struct ptr_valid_map {
219         const char *start, *end;
220         bool is_write;
221 };
222
223 #if HAVE_ALIGNOF
224 #define PTR_VALID_ALIGNOF(var) __alignof__(var)
225 #else
226 /* Can't check this... */
227 #define PTR_VALID_ALIGNOF(var) 1
228 #endif
229 #endif /* CCAN_PTR_VALID_H */