1 /*
2 * (c) 2009-2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 *
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
9 *
10 * As a special exception, you may use this file as part of a free software
11 * library without restriction. Specifically, if other files instantiate
12 * templates or use macros or inline functions from this file, or you compile
13 * this file and link it with other files to produce an executable, this
14 * file does not by itself cause the resulting executable to be covered by
15 * the GNU General Public License. This exception does not however
16 * invalidate any other reasons why the executable file might be covered by
17 * the GNU General Public License.
18 */
19
20 /**
21 * \file
22 * The C IPC gate interface.
23 *
24 * IPC gates are used to create secure communication channels between protection
25 * domains. An IPC gate can be created using the \ref l4_factory_api interface.
26 *
27 * Depending on the permissions of the capability used, an IPC gate forwards IPC
28 * to the \ref l4_thread_api that is *bound* to the IPC gate (cf.
29 * l4_ipc_gate_bind_thread()). If the capability has the #L4_FPAGE_C_IPCGATE_SVR
30 * permission, only IPC using a protocol different from the #L4_PROTO_KOBJECT
31 * protocol is forwarded. Without the #L4_FPAGE_C_IPCGATE_SVR permission, all
32 * IPC is forwarded. The latter is the usual case for a client in a
33 * client/server scenario. When no thread is bound yet, the forwarded IPC blocks
34 * until a thread is bound or the IPC times out.
35 *
36 * Forwarded IPC is always forwarded to the userland of the bound thread. That
37 * means, the \ref l4_thread_api interface of the bound thread is not accessible
38 * via an IPC gate. The \ref l4_kernel_object_gate_api of an IPC gate is only
39 * accessible if the capability used has the #L4_FPAGE_C_IPCGATE_SVR permission
40 * (cf. previous paragraph). Conversely that means, if the capability used lacks
41 * the #L4_FPAGE_C_IPCGATE_SVR permission, \ref l4_kernel_object_gate_api calls
42 * are forwarded to the bound thread instead of being processed by the IPC gate
43 * itself. In a client/server scenario, a client should only get IPC gate
44 * capabilities without #L4_FPAGE_C_IPCGATE_SVR permission so the client cannot
45 * tamper with the IPC gate.
46 *
47 * When binding a thread to an IPC gate, a user-defined, kernel protected,
48 * machine-word sized payload called the IPC gate’s *label* is assigned to the
49 * IPC gate (cf. l4_ipc_gate_bind_thread()). When a send-only IPC or call IPC is
50 * forwarded via an IPC gate, the label provided by the sender is ignored and
51 * replaced by the IPC gate’s label where the two least significant bits are the
52 * result of bitwise disjunction of the corresponding label bits with the
53 * #L4_CAP_FPAGE_S and #L4_CAP_FPAGE_W permissions of the capability used.
54 * Hence, the label provided via l4_ipc_gate_bind_thread() should usually have
55 * its two least significant bits set to zero. The replaced label is only
56 * visible to the bound thread upon receive. However, the configured label of an
57 * IPC gate can also be queried via l4_ipc_gate_get_infos() if the capability
58 * used has the #L4_FPAGE_C_IPCGATE_SVR permission.
59 *
60 * \includefile{l4/sys/ipc_gate.h}
61 *
62 * For the C++ interface refer to the L4::Ipc_gate documentation.
63 *
64 * \see \ref l4_ipc_api
65 */
66
67 #pragma once
68
69 #include <l4/sys/utcb.h>
70 #include <l4/sys/types.h>
71 #include <l4/sys/rcv_endpoint.h>
72
73 /**
74 * \ingroup l4_kernel_object_gate_api
75 * \copybrief L4::Ipc_gate::get_infos
76 * \param gate The IPC gate object to get information about.
77 * \copydetails L4::Ipc_gate::get_infos
78 */
79 L4_INLINE l4_msgtag_t
80 l4_ipc_gate_get_infos(l4_cap_idx_t gate, l4_umword_t *label);
81
82 /**
83 * \internal
84 * \ingroup l4_kernel_object_gate_api
85 */
86 L4_INLINE l4_msgtag_t
87 l4_ipc_gate_get_infos_u(l4_cap_idx_t gate, l4_umword_t *label, l4_utcb_t *utcb);
88
89 /**
90 * Operations on the IPC-gate.
91 * \ingroup l4_protocol_ops
92 * \hideinitializer
93 * \internal
94 */
95 enum L4_ipc_gate_ops
96 {
97 L4_IPC_GATE_BIND_OP = 0x10, /**< Bind operation */
98 L4_IPC_GATE_GET_INFO_OP = 0x11, /**< Info operation */
99 };
100
101
102 /* IMPLEMENTATION -----------------------------------------------------------*/
103
104 #include <l4/sys/ipc.h>
105
106 L4_INLINE l4_msgtag_t
l4_ipc_gate_bind_thread_u(l4_cap_idx_t gate,l4_cap_idx_t thread,l4_umword_t label,l4_utcb_t * utcb)107 l4_ipc_gate_bind_thread_u(l4_cap_idx_t gate,
108 l4_cap_idx_t thread, l4_umword_t label,
109 l4_utcb_t *utcb)
110 {
111 return l4_rcv_ep_bind_thread_u(gate, thread, label, utcb);
112 }
113
114 L4_INLINE l4_msgtag_t
l4_ipc_gate_get_infos_u(l4_cap_idx_t gate,l4_umword_t * label,l4_utcb_t * utcb)115 l4_ipc_gate_get_infos_u(l4_cap_idx_t gate, l4_umword_t *label, l4_utcb_t *utcb)
116 {
117 l4_msgtag_t tag;
118 l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
119 m->mr[0] = L4_IPC_GATE_GET_INFO_OP;
120 tag = l4_ipc_call(gate, utcb, l4_msgtag(L4_PROTO_KOBJECT, 1, 0, 0),
121 L4_IPC_NEVER);
122 if (!l4_msgtag_has_error(tag) && l4_msgtag_label(tag) >= 0)
123 *label = m->mr[0];
124
125 return tag;
126 }
127
128
129
130 L4_INLINE l4_msgtag_t
l4_ipc_gate_bind_thread(l4_cap_idx_t gate,l4_cap_idx_t thread,l4_umword_t label)131 l4_ipc_gate_bind_thread(l4_cap_idx_t gate, l4_cap_idx_t thread,
132 l4_umword_t label)
133 {
134 return l4_rcv_ep_bind_thread_u(gate, thread, label, l4_utcb());
135 }
136
137 L4_INLINE l4_msgtag_t
l4_ipc_gate_get_infos(l4_cap_idx_t gate,l4_umword_t * label)138 l4_ipc_gate_get_infos(l4_cap_idx_t gate, l4_umword_t *label)
139 {
140 return l4_ipc_gate_get_infos_u(gate, label, l4_utcb());
141 }
142