1 /*
2  * xentoolcore_internal.h
3  *
4  * Interfaces of xentoolcore directed internally at other Xen libraries
5  *
6  * Copyright (c) 2017 Citrix
7  *
8  * Common code used by all Xen tools libraries
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation;
13  * version 2.1 of the License.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef XENTOOLCORE_INTERNAL_H
25 #define XENTOOLCORE_INTERNAL_H
26 
27 #include <stddef.h>
28 
29 #include "xentoolcore.h"
30 #include "_xentoolcore_list.h"
31 
32 /*---------- active handle registration ----------*/
33 
34 /*
35  * This is all to support xentoolcore_restrict_all
36  *
37  * Any libxl library that opens a Xen control handle of any kind which
38  * might allow manipulation of dom0, of other domains, or of the whole
39  * machine, must:
40  *   I. arrange that their own datastructure contains a
41  *          Xentoolcore__Active_Handle
42  *
43  *   II. during the "open handle" function
44  *     1. allocate the memory for the own datastructure and initialise it
45  *     2. set Xentoolcore__Active_Handle.restrict_callback
46  *     3. call xentoolcore__register_active_handle
47  *       3a. if the open fails, call xentoolcore__deregister_active_handle
48  *     4. ONLY THEN actually open the relevant fd or whatever
49  *
50  *   III. during the "close handle" function
51  *     1. FIRST call xentoolcore__deregister_active_handle
52  *     2. close the relevant fd or whatever
53  *
54  * [ III(b). Do the same as III for error exit from the open function. ]
55  *
56  *   IV. in the restrict_callback function
57  *     * Arrange that the fd (or other handle) can no longer by used
58  *       other than with respect to domain domid.
59  *     * Future attempts to manipulate other domains (or the whole
60  *       host) via this handle must cause an error return (and
61  *       perhaps a log message), not a crash
62  *     * If selective restriction is not possible, the handle must
63  *       be completely invalidated so that it is not useable;
64  *       subsequent manipulations may not crash
65  *     * The restrict_callback function should not normally fail
66  *       if this can be easily avoided - it is better to make the
67  *       handle nonfunction instead.
68  *     * NB that restrict_callback might be called again.  That must
69  *       work properly: if the domid is the same, it is idempotent.
70  *       If the domid is different. then either the handle must be
71  *       completely invalidated, or restrict_callback must fail.)
72  *
73  * Thread safety:
74  *    xentoolcore__[de]register_active_handle are threadsafe
75  *      but MUST NOT be called within restrict_callback
76  *
77  * Fork safety:
78  *    Libraries which use these functions do not on that account
79  *    need to take any special care over forks occurring in
80  *    other threads, provided that they obey the rules above.
81  */
82 
83 typedef struct Xentoolcore__Active_Handle Xentoolcore__Active_Handle;
84 
85 typedef int Xentoolcore__Restrict_Callback(Xentoolcore__Active_Handle*,
86                                            domid_t domid);
87 
88 struct Xentoolcore__Active_Handle {
89     Xentoolcore__Restrict_Callback *restrict_callback;
90     XENTOOLCORE_LIST_ENTRY(Xentoolcore__Active_Handle) entry;
91 };
92 
93 void xentoolcore__register_active_handle(Xentoolcore__Active_Handle*);
94 void xentoolcore__deregister_active_handle(Xentoolcore__Active_Handle*);
95 
96 /*
97  * Utility function for use in restrict_callback in libraries whose
98  * handles don't have a useful restrict function.  We neuter the fd by
99  * dup'ing /dev/null onto it.  This is better than closing it, because
100  * it does not involve locking against concurrent uses of in other
101  * threads.
102  *
103  * Returns the value that restrict_callback should return.
104  * fd may be < 0.
105  */
106 int xentoolcore__restrict_by_dup2_null(int fd);
107 
108 /* ---------- convenient stuff ---------- */
109 
110 /*
111  * This does not appear in xentoolcore.h because it is a bit
112  * namespace-unclean.
113  */
114 
115 /*
116  * Convenience macros.
117  */
118 
119 /*
120  * CONTAINER_OF work like this.  Given:
121  *    typedef struct {
122  *      ...
123  *      member_type member_name;
124  *      ...
125  *    } outer_type;
126  *    outer_type outer, *outer_var;
127  *    member_type *inner_ptr = &outer->member_name;
128  *
129  * Then, effectively:
130  *    outer_type *CONTAINER_OF(member_type *inner_ptr,
131  *                             *outer_var, // or type name for outer_type
132  *                             member_name);
133  *
134  * So that:
135  *    CONTAINER_OF(inner_ptr, *outer_var, member_name) == &outer
136  *    CONTAINER_OF(inner_ptr, outer_type, member_name) == &outer
137  */
138 #define CONTAINER_OF(inner_ptr, outer, member_name)                     \
139     ({                                                                  \
140         typeof(outer) *container_of_;                                   \
141         container_of_ = (void*)((char*)(inner_ptr) -                    \
142                                 offsetof(typeof(outer), member_name));  \
143         (void)(&container_of_->member_name ==                           \
144                (typeof(inner_ptr))0) /* type check */;                  \
145         container_of_;                                                  \
146     })
147 
148 #endif /* XENTOOLCORE_INTERNAL_H */
149 
150 /*
151  * Local variables:
152  * mode: C
153  * c-file-style: "BSD"
154  * c-basic-offset: 4
155  * tab-width: 4
156  * indent-tabs-mode: nil
157  * End:
158  */
159