mac_inet.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*-
  2. * Copyright (c) 1999-2002, 2007, 2009, 2019 Robert N. M. Watson
  3. * Copyright (c) 2001 Ilmar S. Habibulin
  4. * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
  5. * Copyright (c) 2006 SPARTA, Inc.
  6. * Copyright (c) 2008 Apple Inc.
  7. * All rights reserved.
  8. *
  9. * This software was developed by Robert Watson and Ilmar Habibulin for the
  10. * TrustedBSD Project.
  11. *
  12. * This software was developed for the FreeBSD Project in part by Network
  13. * Associates Laboratories, the Security Research Division of Network
  14. * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
  15. * as part of the DARPA CHATS research program.
  16. *
  17. * This software was enhanced by SPARTA ISSO under SPAWAR contract
  18. * N66001-04-C-6019 ("SEFOS").
  19. *
  20. * This software was developed at the University of Cambridge Computer
  21. * Laboratory with support from a grant from Google, Inc.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the above copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  33. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  36. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  40. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  42. * SUCH DAMAGE.
  43. */
  44. #include <sys/cdefs.h>
  45. #include "opt_mac.h"
  46. #include <sys/param.h>
  47. #include <sys/kernel.h>
  48. #include <sys/lock.h>
  49. #include <sys/malloc.h>
  50. #include <sys/mutex.h>
  51. #include <sys/sbuf.h>
  52. #include <sys/sdt.h>
  53. #include <sys/systm.h>
  54. #include <sys/mount.h>
  55. #include <sys/file.h>
  56. #include <sys/namei.h>
  57. #include <sys/protosw.h>
  58. #include <sys/socket.h>
  59. #include <sys/socketvar.h>
  60. #include <sys/sysctl.h>
  61. #include <net/if.h>
  62. #include <net/if_var.h>
  63. #include <netinet/in.h>
  64. #include <netinet/in_pcb.h>
  65. #include <netinet/ip_var.h>
  66. #include <security/mac/mac_framework.h>
  67. #include <security/mac/mac_internal.h>
  68. #include <security/mac/mac_policy.h>
  69. static struct label *
  70. mac_inpcb_label_alloc(int flag)
  71. {
  72. struct label *label;
  73. int error;
  74. label = mac_labelzone_alloc(flag);
  75. if (label == NULL)
  76. return (NULL);
  77. if (flag & M_WAITOK)
  78. MAC_POLICY_CHECK(inpcb_init_label, label, flag);
  79. else
  80. MAC_POLICY_CHECK_NOSLEEP(inpcb_init_label, label, flag);
  81. if (error) {
  82. MAC_POLICY_PERFORM_NOSLEEP(inpcb_destroy_label, label);
  83. mac_labelzone_free(label);
  84. return (NULL);
  85. }
  86. return (label);
  87. }
  88. int
  89. mac_inpcb_init(struct inpcb *inp, int flag)
  90. {
  91. if (mac_labeled & MPC_OBJECT_INPCB) {
  92. inp->inp_label = mac_inpcb_label_alloc(flag);
  93. if (inp->inp_label == NULL)
  94. return (ENOMEM);
  95. } else
  96. inp->inp_label = NULL;
  97. return (0);
  98. }
  99. /* Check with rules in module if the IPv4 address is allowed. */
  100. int
  101. mac_inet_check_add_addr(struct ucred *cred, const struct in_addr *ia,
  102. struct ifnet *ifp)
  103. {
  104. int error;
  105. MAC_POLICY_CHECK(ip4_check_jail, cred, ia, ifp);
  106. return (error);
  107. }
  108. static struct label *
  109. mac_ipq_label_alloc(int flag)
  110. {
  111. struct label *label;
  112. int error;
  113. label = mac_labelzone_alloc(flag);
  114. if (label == NULL)
  115. return (NULL);
  116. if (flag & M_WAITOK)
  117. MAC_POLICY_CHECK(ipq_init_label, label, flag);
  118. else
  119. MAC_POLICY_CHECK_NOSLEEP(ipq_init_label, label, flag);
  120. if (error) {
  121. MAC_POLICY_PERFORM_NOSLEEP(ipq_destroy_label, label);
  122. mac_labelzone_free(label);
  123. return (NULL);
  124. }
  125. return (label);
  126. }
  127. int
  128. mac_ipq_init(struct ipq *q, int flag)
  129. {
  130. if (mac_labeled & MPC_OBJECT_IPQ) {
  131. q->ipq_label = mac_ipq_label_alloc(flag);
  132. if (q->ipq_label == NULL)
  133. return (ENOMEM);
  134. } else
  135. q->ipq_label = NULL;
  136. return (0);
  137. }
  138. static void
  139. mac_inpcb_label_free(struct label *label)
  140. {
  141. MAC_POLICY_PERFORM_NOSLEEP(inpcb_destroy_label, label);
  142. mac_labelzone_free(label);
  143. }
  144. void
  145. mac_inpcb_destroy(struct inpcb *inp)
  146. {
  147. if (inp->inp_label != NULL) {
  148. mac_inpcb_label_free(inp->inp_label);
  149. inp->inp_label = NULL;
  150. }
  151. }
  152. static void
  153. mac_ipq_label_free(struct label *label)
  154. {
  155. MAC_POLICY_PERFORM_NOSLEEP(ipq_destroy_label, label);
  156. mac_labelzone_free(label);
  157. }
  158. void
  159. mac_ipq_destroy(struct ipq *q)
  160. {
  161. if (q->ipq_label != NULL) {
  162. mac_ipq_label_free(q->ipq_label);
  163. q->ipq_label = NULL;
  164. }
  165. }
  166. void
  167. mac_inpcb_create(struct socket *so, struct inpcb *inp)
  168. {
  169. MAC_POLICY_PERFORM_NOSLEEP(inpcb_create, so, so->so_label, inp,
  170. inp->inp_label);
  171. }
  172. void
  173. mac_ipq_reassemble(struct ipq *q, struct mbuf *m)
  174. {
  175. struct label *label;
  176. if (mac_policy_count == 0)
  177. return;
  178. label = mac_mbuf_to_label(m);
  179. MAC_POLICY_PERFORM_NOSLEEP(ipq_reassemble, q, q->ipq_label, m,
  180. label);
  181. }
  182. void
  183. mac_netinet_fragment(struct mbuf *m, struct mbuf *frag)
  184. {
  185. struct label *mlabel, *fraglabel;
  186. if (mac_policy_count == 0)
  187. return;
  188. mlabel = mac_mbuf_to_label(m);
  189. fraglabel = mac_mbuf_to_label(frag);
  190. MAC_POLICY_PERFORM_NOSLEEP(netinet_fragment, m, mlabel, frag,
  191. fraglabel);
  192. }
  193. void
  194. mac_ipq_create(struct mbuf *m, struct ipq *q)
  195. {
  196. struct label *label;
  197. if (mac_policy_count == 0)
  198. return;
  199. label = mac_mbuf_to_label(m);
  200. MAC_POLICY_PERFORM_NOSLEEP(ipq_create, m, label, q, q->ipq_label);
  201. }
  202. void
  203. mac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m)
  204. {
  205. struct label *mlabel;
  206. INP_LOCK_ASSERT(inp);
  207. if (mac_policy_count == 0)
  208. return;
  209. mlabel = mac_mbuf_to_label(m);
  210. MAC_POLICY_PERFORM_NOSLEEP(inpcb_create_mbuf, inp, inp->inp_label, m,
  211. mlabel);
  212. }
  213. int
  214. mac_ipq_match(struct mbuf *m, struct ipq *q)
  215. {
  216. struct label *label;
  217. int result;
  218. if (mac_policy_count == 0)
  219. return (1);
  220. label = mac_mbuf_to_label(m);
  221. result = 1;
  222. MAC_POLICY_BOOLEAN_NOSLEEP(ipq_match, &&, m, label, q, q->ipq_label);
  223. return (result);
  224. }
  225. void
  226. mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m)
  227. {
  228. struct label *mlabel;
  229. int locked;
  230. if (mac_policy_count == 0)
  231. return;
  232. mlabel = mac_mbuf_to_label(m);
  233. MAC_IFNET_LOCK(ifp, locked);
  234. MAC_POLICY_PERFORM_NOSLEEP(netinet_arp_send, ifp, if_getmaclabel(ifp),
  235. m, mlabel);
  236. MAC_IFNET_UNLOCK(ifp, locked);
  237. }
  238. void
  239. mac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend)
  240. {
  241. struct label *mrecvlabel, *msendlabel;
  242. if (mac_policy_count == 0)
  243. return;
  244. mrecvlabel = mac_mbuf_to_label(mrecv);
  245. msendlabel = mac_mbuf_to_label(msend);
  246. MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_reply, mrecv, mrecvlabel,
  247. msend, msendlabel);
  248. }
  249. void
  250. mac_netinet_icmp_replyinplace(struct mbuf *m)
  251. {
  252. struct label *label;
  253. if (mac_policy_count == 0)
  254. return;
  255. label = mac_mbuf_to_label(m);
  256. MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_replyinplace, m, label);
  257. }
  258. void
  259. mac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m)
  260. {
  261. struct label *mlabel;
  262. int locked;
  263. if (mac_policy_count == 0)
  264. return;
  265. mlabel = mac_mbuf_to_label(m);
  266. MAC_IFNET_LOCK(ifp, locked);
  267. MAC_POLICY_PERFORM_NOSLEEP(netinet_igmp_send, ifp, if_getmaclabel(ifp),
  268. m, mlabel);
  269. MAC_IFNET_UNLOCK(ifp, locked);
  270. }
  271. void
  272. mac_netinet_tcp_reply(struct mbuf *m)
  273. {
  274. struct label *label;
  275. if (mac_policy_count == 0)
  276. return;
  277. label = mac_mbuf_to_label(m);
  278. MAC_POLICY_PERFORM_NOSLEEP(netinet_tcp_reply, m, label);
  279. }
  280. void
  281. mac_ipq_update(struct mbuf *m, struct ipq *q)
  282. {
  283. struct label *label;
  284. if (mac_policy_count == 0)
  285. return;
  286. label = mac_mbuf_to_label(m);
  287. MAC_POLICY_PERFORM_NOSLEEP(ipq_update, m, label, q, q->ipq_label);
  288. }
  289. MAC_CHECK_PROBE_DEFINE2(inpcb_check_deliver, "struct inpcb *",
  290. "struct mbuf *");
  291. int
  292. mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m)
  293. {
  294. struct label *label;
  295. int error;
  296. M_ASSERTPKTHDR(m);
  297. if (mac_policy_count == 0)
  298. return (0);
  299. label = mac_mbuf_to_label(m);
  300. MAC_POLICY_CHECK_NOSLEEP(inpcb_check_deliver, inp, inp->inp_label, m,
  301. label);
  302. MAC_CHECK_PROBE2(inpcb_check_deliver, error, inp, m);
  303. return (error);
  304. }
  305. MAC_CHECK_PROBE_DEFINE2(inpcb_check_visible, "struct ucred *",
  306. "struct inpcb *");
  307. int
  308. mac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp)
  309. {
  310. int error;
  311. INP_LOCK_ASSERT(inp);
  312. MAC_POLICY_CHECK_NOSLEEP(inpcb_check_visible, cred, inp,
  313. inp->inp_label);
  314. MAC_CHECK_PROBE2(inpcb_check_visible, error, cred, inp);
  315. return (error);
  316. }
  317. void
  318. mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
  319. {
  320. INP_WLOCK_ASSERT(inp);
  321. SOCK_LOCK_ASSERT(so);
  322. MAC_POLICY_PERFORM_NOSLEEP(inpcb_sosetlabel, so, so->so_label, inp,
  323. inp->inp_label);
  324. }
  325. void
  326. mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend)
  327. {
  328. struct label *mrecvlabel, *msendlabel;
  329. M_ASSERTPKTHDR(mrecv);
  330. M_ASSERTPKTHDR(msend);
  331. if (mac_policy_count == 0)
  332. return;
  333. mrecvlabel = mac_mbuf_to_label(mrecv);
  334. msendlabel = mac_mbuf_to_label(msend);
  335. MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_reply, mrecv, mrecvlabel,
  336. msend, msendlabel);
  337. }
  338. void
  339. mac_netinet_firewall_send(struct mbuf *m)
  340. {
  341. struct label *label;
  342. M_ASSERTPKTHDR(m);
  343. if (mac_policy_count == 0)
  344. return;
  345. label = mac_mbuf_to_label(m);
  346. MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_send, m, label);
  347. }
  348. /*
  349. * These functions really should be referencing the syncache structure
  350. * instead of the label. However, due to some of the complexities associated
  351. * with exposing this syncache structure we operate directly on its label
  352. * pointer. This should be OK since we aren't making any access control
  353. * decisions within this code directly, we are merely allocating and copying
  354. * label storage so we can properly initialize mbuf labels for any packets
  355. * the syncache code might create.
  356. */
  357. void
  358. mac_syncache_destroy(struct label **label)
  359. {
  360. if (*label != NULL) {
  361. MAC_POLICY_PERFORM_NOSLEEP(syncache_destroy_label, *label);
  362. mac_labelzone_free(*label);
  363. *label = NULL;
  364. }
  365. }
  366. int
  367. mac_syncache_init(struct label **label)
  368. {
  369. int error;
  370. if (mac_labeled & MPC_OBJECT_SYNCACHE) {
  371. *label = mac_labelzone_alloc(M_NOWAIT);
  372. if (*label == NULL)
  373. return (ENOMEM);
  374. /*
  375. * Since we are holding the inpcb locks the policy can not
  376. * allocate policy specific label storage using M_WAITOK. So
  377. * we need to do a MAC_CHECK instead of the typical
  378. * MAC_PERFORM so we can propagate allocation failures back
  379. * to the syncache code.
  380. */
  381. MAC_POLICY_CHECK_NOSLEEP(syncache_init_label, *label,
  382. M_NOWAIT);
  383. if (error) {
  384. MAC_POLICY_PERFORM_NOSLEEP(syncache_destroy_label,
  385. *label);
  386. mac_labelzone_free(*label);
  387. }
  388. return (error);
  389. } else
  390. *label = NULL;
  391. return (0);
  392. }
  393. void
  394. mac_syncache_create(struct label *label, struct inpcb *inp)
  395. {
  396. INP_LOCK_ASSERT(inp);
  397. MAC_POLICY_PERFORM_NOSLEEP(syncache_create, label, inp);
  398. }
  399. void
  400. mac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m)
  401. {
  402. struct label *mlabel;
  403. M_ASSERTPKTHDR(m);
  404. if (mac_policy_count == 0)
  405. return;
  406. mlabel = mac_mbuf_to_label(m);
  407. MAC_POLICY_PERFORM_NOSLEEP(syncache_create_mbuf, sc_label, m,
  408. mlabel);
  409. }