1 |
/* |
2 |
* include/linux/tomoyo_socket.h |
3 |
* |
4 |
* Implementation of the Domain-Based Mandatory Access Control. |
5 |
* |
6 |
* Copyright (C) 2005-2007 NTT DATA CORPORATION |
7 |
* |
8 |
* Version: 1.4.2 2007/07/13 |
9 |
* |
10 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
11 |
* See README.ccs for ChangeLog. |
12 |
* |
13 |
*/ |
14 |
|
15 |
#ifndef _LINUX_TOMOYO_SOCKET_H |
16 |
#define _LINUX_TOMOYO_SOCKET_H |
17 |
|
18 |
/***** TOMOYO Linux start. *****/ |
19 |
|
20 |
#include <net/ip.h> |
21 |
#include <net/ipv6.h> |
22 |
|
23 |
#include <linux/version.h> |
24 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
25 |
#define sk_family family |
26 |
#define sk_protocol protocol |
27 |
#endif |
28 |
|
29 |
#define MAX_SOCK_ADDR 128 /* net/socket.c */ |
30 |
|
31 |
static int CheckSocketCreatePermission(int family, int type, int protocol) |
32 |
{ |
33 |
int error = 0; |
34 |
if (family == PF_INET || family == PF_INET6) { |
35 |
switch (type) { |
36 |
case SOCK_STREAM: |
37 |
error = CheckCapabilityACL(TOMOYO_INET_STREAM_SOCKET_CREATE); |
38 |
break; |
39 |
case SOCK_DGRAM: |
40 |
error = CheckCapabilityACL(TOMOYO_USE_INET_DGRAM_SOCKET); |
41 |
break; |
42 |
case SOCK_RAW: |
43 |
error = CheckCapabilityACL(TOMOYO_USE_INET_RAW_SOCKET); |
44 |
break; |
45 |
} |
46 |
} else if (family == PF_PACKET) { |
47 |
error = CheckCapabilityACL(TOMOYO_USE_PACKET_SOCKET); |
48 |
} else if (family == PF_ROUTE) { |
49 |
error = CheckCapabilityACL(TOMOYO_USE_ROUTE_SOCKET); |
50 |
} |
51 |
return error; |
52 |
} |
53 |
|
54 |
static int CheckSocketListenPermission(struct socket *sock) |
55 |
{ |
56 |
int error = 0; |
57 |
if (sock->type == SOCK_STREAM) { |
58 |
switch (sock->sk->sk_family) { |
59 |
case PF_INET: |
60 |
case PF_INET6: |
61 |
error = CheckCapabilityACL(TOMOYO_INET_STREAM_SOCKET_LISTEN); |
62 |
if (!error) { |
63 |
char addr[MAX_SOCK_ADDR]; |
64 |
int addr_len; |
65 |
if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0) == 0) { |
66 |
switch (((struct sockaddr *) addr)->sa_family) { |
67 |
case AF_INET6: |
68 |
error = CheckNetworkListenACL(1, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, ((struct sockaddr_in6 *) addr)->sin6_port); |
69 |
break; |
70 |
case AF_INET: |
71 |
error = CheckNetworkListenACL(0, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, ((struct sockaddr_in *) addr)->sin_port); |
72 |
break; |
73 |
} |
74 |
} else { |
75 |
error = -EPERM; |
76 |
} |
77 |
} |
78 |
break; |
79 |
} |
80 |
} |
81 |
return error; |
82 |
} |
83 |
|
84 |
static int CheckSocketConnectPermission(struct socket *sock, struct sockaddr *addr, int addr_len) |
85 |
{ |
86 |
int error = 0; |
87 |
const unsigned int type = sock->type; |
88 |
if (type == SOCK_STREAM || type == SOCK_DGRAM || type == SOCK_RAW) { |
89 |
switch (addr->sa_family) { |
90 |
case AF_INET6: |
91 |
if (addr_len >= SIN6_LEN_RFC2133) { |
92 |
if (type != SOCK_RAW) { |
93 |
error = CheckNetworkConnectACL(1, type, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, ((struct sockaddr_in6 *) addr)->sin6_port); |
94 |
} else { |
95 |
error = CheckNetworkConnectACL(1, SOCK_RAW, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, htons(sock->sk->sk_protocol)); |
96 |
} |
97 |
} |
98 |
break; |
99 |
case AF_INET: |
100 |
if (addr_len >= sizeof(struct sockaddr_in)) { |
101 |
if (type != SOCK_RAW) { |
102 |
error = CheckNetworkConnectACL(0, type, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, ((struct sockaddr_in *) addr)->sin_port); |
103 |
} else { |
104 |
error = CheckNetworkConnectACL(0, SOCK_RAW, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, htons(sock->sk->sk_protocol)); |
105 |
} |
106 |
} |
107 |
break; |
108 |
} |
109 |
} |
110 |
if (type == SOCK_STREAM) { |
111 |
switch (sock->sk->sk_family) { |
112 |
case PF_INET: |
113 |
case PF_INET6: |
114 |
error = CheckCapabilityACL(TOMOYO_INET_STREAM_SOCKET_CONNECT) ? -EPERM : error; |
115 |
break; |
116 |
} |
117 |
} |
118 |
return error; |
119 |
} |
120 |
|
121 |
static int CheckSocketBindPermission(struct socket *sock, struct sockaddr *addr, int addr_len) |
122 |
{ |
123 |
int error = 0; |
124 |
const unsigned int type = sock->type; |
125 |
if (type == SOCK_STREAM || type == SOCK_DGRAM || type == SOCK_RAW) { |
126 |
switch (addr->sa_family) { |
127 |
case AF_INET6: |
128 |
if (addr_len >= SIN6_LEN_RFC2133) { |
129 |
if (type != SOCK_RAW) { |
130 |
error = CheckNetworkBindACL(1, type, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, ((struct sockaddr_in6 *) addr)->sin6_port); |
131 |
} else { |
132 |
error = CheckNetworkBindACL(1, SOCK_RAW, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, htons(sock->sk->sk_protocol)); |
133 |
} |
134 |
} |
135 |
break; |
136 |
case AF_INET: |
137 |
if (addr_len >= sizeof(struct sockaddr_in)) { |
138 |
if (type != SOCK_RAW) { |
139 |
error = CheckNetworkBindACL(0, type, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, ((struct sockaddr_in *) addr)->sin_port); |
140 |
} else { |
141 |
error = CheckNetworkBindACL(0, SOCK_RAW, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, htons(sock->sk->sk_protocol)); |
142 |
} |
143 |
} |
144 |
break; |
145 |
} |
146 |
} |
147 |
return error; |
148 |
} |
149 |
|
150 |
static int CheckSocketAcceptPermission(struct socket *sock, struct sockaddr *addr) |
151 |
{ |
152 |
int error = 0; |
153 |
int addr_len; |
154 |
switch (sock->sk->sk_family) { |
155 |
case PF_INET: |
156 |
case PF_INET6: |
157 |
if (sock->ops->getname(sock, addr, &addr_len, 2) == 0) { |
158 |
switch (addr->sa_family) { |
159 |
case AF_INET6: |
160 |
error = CheckNetworkAcceptACL(1, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, ((struct sockaddr_in6 *) addr)->sin6_port); |
161 |
break; |
162 |
case AF_INET: |
163 |
error = CheckNetworkAcceptACL(0, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, ((struct sockaddr_in *) addr)->sin_port); |
164 |
break; |
165 |
} |
166 |
} else { |
167 |
error = -EPERM; |
168 |
} |
169 |
} |
170 |
return error; |
171 |
} |
172 |
|
173 |
static int CheckSocketSendMsgPermission(struct socket *sock, struct sockaddr *addr, int addr_len) |
174 |
{ |
175 |
int error = 0; |
176 |
const int type = sock->type; |
177 |
if (addr && (type == SOCK_DGRAM || type == SOCK_RAW)) { |
178 |
switch (addr->sa_family) { |
179 |
case AF_INET6: |
180 |
if (addr_len >= SIN6_LEN_RFC2133) { |
181 |
error = CheckNetworkSendMsgACL(1, type, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, type == SOCK_DGRAM ? ((struct sockaddr_in6 *) addr)->sin6_port : htons(sock->sk->sk_protocol)); |
182 |
} |
183 |
break; |
184 |
case AF_INET: |
185 |
if (addr_len >= sizeof(struct sockaddr_in)) { |
186 |
error = CheckNetworkSendMsgACL(0, type, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, type == SOCK_DGRAM ? ((struct sockaddr_in *) addr)->sin_port : htons(sock->sk->sk_protocol)); |
187 |
} |
188 |
break; |
189 |
} |
190 |
} |
191 |
return error; |
192 |
} |
193 |
|
194 |
static int CheckSocketRecvMsgPermission(struct socket *sock, struct sockaddr *addr, int addr_len) |
195 |
{ |
196 |
int error = 0; |
197 |
const unsigned int type = sock->type; |
198 |
if (addr && (type == SOCK_DGRAM || type == SOCK_RAW)) { |
199 |
switch (addr->sa_family) { |
200 |
case AF_INET6: |
201 |
if (addr_len >= SIN6_LEN_RFC2133) error = CheckNetworkRecvMsgACL(1, type, ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, type == SOCK_DGRAM ? ((struct sockaddr_in6 *) addr)->sin6_port : htons(sock->sk->sk_protocol)); |
202 |
break; |
203 |
case AF_INET: |
204 |
if (addr_len >= sizeof(struct sockaddr_in)) error = CheckNetworkRecvMsgACL(0, type, (u8 *) &((struct sockaddr_in *) addr)->sin_addr, type == SOCK_DGRAM ? ((struct sockaddr_in *) addr)->sin_port : htons(sock->sk->sk_protocol)); |
205 |
break; |
206 |
} |
207 |
} |
208 |
return error; |
209 |
} |
210 |
|
211 |
/***** TOMOYO Linux end. *****/ |
212 |
#endif |