netlabel.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * SELinux NetLabel Support
  4. *
  5. * This file provides the necessary glue to tie NetLabel into the SELinux
  6. * subsystem.
  7. *
  8. * Author: Paul Moore <paul@paul-moore.com>
  9. */
  10. /*
  11. * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
  12. */
  13. #include <linux/spinlock.h>
  14. #include <linux/rcupdate.h>
  15. #include <linux/gfp.h>
  16. #include <linux/ip.h>
  17. #include <linux/ipv6.h>
  18. #include <net/sock.h>
  19. #include <net/netlabel.h>
  20. #include <net/ip.h>
  21. #include <net/ipv6.h>
  22. #include "objsec.h"
  23. #include "security.h"
  24. #include "netlabel.h"
  25. /**
  26. * selinux_netlbl_sidlookup_cached - Cache a SID lookup
  27. * @skb: the packet
  28. * @secattr: the NetLabel security attributes
  29. * @sid: the SID
  30. *
  31. * Description:
  32. * Query the SELinux security server to lookup the correct SID for the given
  33. * security attributes. If the query is successful, cache the result to speed
  34. * up future lookups. Returns zero on success, negative values on failure.
  35. *
  36. */
  37. static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
  38. u16 family,
  39. struct netlbl_lsm_secattr *secattr,
  40. u32 *sid)
  41. {
  42. int rc;
  43. rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
  44. if (rc == 0 &&
  45. (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
  46. (secattr->flags & NETLBL_SECATTR_CACHE))
  47. netlbl_cache_add(skb, family, secattr);
  48. return rc;
  49. }
  50. /**
  51. * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
  52. * @sk: the socket
  53. *
  54. * Description:
  55. * Generate the NetLabel security attributes for a socket, making full use of
  56. * the socket's attribute cache. Returns a pointer to the security attributes
  57. * on success, NULL on failure.
  58. *
  59. */
  60. static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
  61. {
  62. int rc;
  63. struct sk_security_struct *sksec = sk->sk_security;
  64. struct netlbl_lsm_secattr *secattr;
  65. if (sksec->nlbl_secattr != NULL)
  66. return sksec->nlbl_secattr;
  67. secattr = netlbl_secattr_alloc(GFP_ATOMIC);
  68. if (secattr == NULL)
  69. return NULL;
  70. rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
  71. secattr);
  72. if (rc != 0) {
  73. netlbl_secattr_free(secattr);
  74. return NULL;
  75. }
  76. sksec->nlbl_secattr = secattr;
  77. return secattr;
  78. }
  79. /**
  80. * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
  81. * @sk: the socket
  82. * @sid: the SID
  83. *
  84. * Query the socket's cached secattr and if the SID matches the cached value
  85. * return the cache, otherwise return NULL.
  86. *
  87. */
  88. static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
  89. const struct sock *sk,
  90. u32 sid)
  91. {
  92. struct sk_security_struct *sksec = sk->sk_security;
  93. struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
  94. if (secattr == NULL)
  95. return NULL;
  96. if ((secattr->flags & NETLBL_SECATTR_SECID) &&
  97. (secattr->attr.secid == sid))
  98. return secattr;
  99. return NULL;
  100. }
  101. /**
  102. * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
  103. *
  104. * Description:
  105. * Invalidate the NetLabel security attribute mapping cache.
  106. *
  107. */
  108. void selinux_netlbl_cache_invalidate(void)
  109. {
  110. netlbl_cache_invalidate();
  111. }
  112. /**
  113. * selinux_netlbl_err - Handle a NetLabel packet error
  114. * @skb: the packet
  115. * @error: the error code
  116. * @gateway: true if host is acting as a gateway, false otherwise
  117. *
  118. * Description:
  119. * When a packet is dropped due to a call to avc_has_perm() pass the error
  120. * code to the NetLabel subsystem so any protocol specific processing can be
  121. * done. This is safe to call even if you are unsure if NetLabel labeling is
  122. * present on the packet, NetLabel is smart enough to only act when it should.
  123. *
  124. */
  125. void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
  126. {
  127. netlbl_skbuff_err(skb, family, error, gateway);
  128. }
  129. /**
  130. * selinux_netlbl_sk_security_free - Free the NetLabel fields
  131. * @sksec: the sk_security_struct
  132. *
  133. * Description:
  134. * Free all of the memory in the NetLabel fields of a sk_security_struct.
  135. *
  136. */
  137. void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
  138. {
  139. if (sksec->nlbl_secattr != NULL)
  140. netlbl_secattr_free(sksec->nlbl_secattr);
  141. }
  142. /**
  143. * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
  144. * @sksec: the sk_security_struct
  145. * @family: the socket family
  146. *
  147. * Description:
  148. * Called when the NetLabel state of a sk_security_struct needs to be reset.
  149. * The caller is responsible for all the NetLabel sk_security_struct locking.
  150. *
  151. */
  152. void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec)
  153. {
  154. sksec->nlbl_state = NLBL_UNSET;
  155. }
  156. /**
  157. * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
  158. * @skb: the packet
  159. * @family: protocol family
  160. * @type: NetLabel labeling protocol type
  161. * @sid: the SID
  162. *
  163. * Description:
  164. * Call the NetLabel mechanism to get the security attributes of the given
  165. * packet and use those attributes to determine the correct context/SID to
  166. * assign to the packet. Returns zero on success, negative values on failure.
  167. *
  168. */
  169. int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
  170. u16 family,
  171. u32 *type,
  172. u32 *sid)
  173. {
  174. int rc;
  175. struct netlbl_lsm_secattr secattr;
  176. if (!netlbl_enabled()) {
  177. *sid = SECSID_NULL;
  178. return 0;
  179. }
  180. netlbl_secattr_init(&secattr);
  181. rc = netlbl_skbuff_getattr(skb, family, &secattr);
  182. if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
  183. rc = selinux_netlbl_sidlookup_cached(skb, family,
  184. &secattr, sid);
  185. else
  186. *sid = SECSID_NULL;
  187. *type = secattr.type;
  188. netlbl_secattr_destroy(&secattr);
  189. return rc;
  190. }
  191. /**
  192. * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
  193. * @skb: the packet
  194. * @family: protocol family
  195. * @sid: the SID
  196. *
  197. * Description
  198. * Call the NetLabel mechanism to set the label of a packet using @sid.
  199. * Returns zero on success, negative values on failure.
  200. *
  201. */
  202. int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
  203. u16 family,
  204. u32 sid)
  205. {
  206. int rc;
  207. struct netlbl_lsm_secattr secattr_storage;
  208. struct netlbl_lsm_secattr *secattr = NULL;
  209. struct sock *sk;
  210. /* if this is a locally generated packet check to see if it is already
  211. * being labeled by it's parent socket, if it is just exit */
  212. sk = skb_to_full_sk(skb);
  213. if (sk != NULL) {
  214. struct sk_security_struct *sksec = sk->sk_security;
  215. if (sksec->nlbl_state != NLBL_REQSKB)
  216. return 0;
  217. secattr = selinux_netlbl_sock_getattr(sk, sid);
  218. }
  219. if (secattr == NULL) {
  220. secattr = &secattr_storage;
  221. netlbl_secattr_init(secattr);
  222. rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
  223. secattr);
  224. if (rc != 0)
  225. goto skbuff_setsid_return;
  226. }
  227. rc = netlbl_skbuff_setattr(skb, family, secattr);
  228. skbuff_setsid_return:
  229. if (secattr == &secattr_storage)
  230. netlbl_secattr_destroy(secattr);
  231. return rc;
  232. }
  233. /**
  234. * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association.
  235. * @ep: incoming association endpoint.
  236. * @skb: the packet.
  237. *
  238. * Description:
  239. * A new incoming connection is represented by @ep, ......
  240. * Returns zero on success, negative values on failure.
  241. *
  242. */
  243. int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
  244. struct sk_buff *skb)
  245. {
  246. int rc;
  247. struct netlbl_lsm_secattr secattr;
  248. struct sk_security_struct *sksec = ep->base.sk->sk_security;
  249. struct sockaddr_in addr4;
  250. struct sockaddr_in6 addr6;
  251. if (ep->base.sk->sk_family != PF_INET &&
  252. ep->base.sk->sk_family != PF_INET6)
  253. return 0;
  254. netlbl_secattr_init(&secattr);
  255. rc = security_netlbl_sid_to_secattr(&selinux_state,
  256. ep->secid, &secattr);
  257. if (rc != 0)
  258. goto assoc_request_return;
  259. /* Move skb hdr address info to a struct sockaddr and then call
  260. * netlbl_conn_setattr().
  261. */
  262. if (ip_hdr(skb)->version == 4) {
  263. addr4.sin_family = AF_INET;
  264. addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
  265. rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr4, &secattr);
  266. } else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) {
  267. addr6.sin6_family = AF_INET6;
  268. addr6.sin6_addr = ipv6_hdr(skb)->saddr;
  269. rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr6, &secattr);
  270. } else {
  271. rc = -EAFNOSUPPORT;
  272. }
  273. if (rc == 0)
  274. sksec->nlbl_state = NLBL_LABELED;
  275. assoc_request_return:
  276. netlbl_secattr_destroy(&secattr);
  277. return rc;
  278. }
  279. /**
  280. * selinux_netlbl_inet_conn_request - Label an incoming stream connection
  281. * @req: incoming connection request socket
  282. *
  283. * Description:
  284. * A new incoming connection request is represented by @req, we need to label
  285. * the new request_sock here and the stack will ensure the on-the-wire label
  286. * will get preserved when a full sock is created once the connection handshake
  287. * is complete. Returns zero on success, negative values on failure.
  288. *
  289. */
  290. int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
  291. {
  292. int rc;
  293. struct netlbl_lsm_secattr secattr;
  294. if (family != PF_INET && family != PF_INET6)
  295. return 0;
  296. netlbl_secattr_init(&secattr);
  297. rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
  298. &secattr);
  299. if (rc != 0)
  300. goto inet_conn_request_return;
  301. rc = netlbl_req_setattr(req, &secattr);
  302. inet_conn_request_return:
  303. netlbl_secattr_destroy(&secattr);
  304. return rc;
  305. }
  306. /**
  307. * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
  308. * @sk: the new sock
  309. *
  310. * Description:
  311. * A new connection has been established using @sk, we've already labeled the
  312. * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
  313. * we need to set the NetLabel state here since we now have a sock structure.
  314. *
  315. */
  316. void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
  317. {
  318. struct sk_security_struct *sksec = sk->sk_security;
  319. if (family == PF_INET)
  320. sksec->nlbl_state = NLBL_LABELED;
  321. else
  322. sksec->nlbl_state = NLBL_UNSET;
  323. }
  324. /**
  325. * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock
  326. * @sk: current sock
  327. * @newsk: the new sock
  328. *
  329. * Description:
  330. * Called whenever a new socket is created by accept(2) or sctp_peeloff(3).
  331. */
  332. void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
  333. {
  334. struct sk_security_struct *sksec = sk->sk_security;
  335. struct sk_security_struct *newsksec = newsk->sk_security;
  336. newsksec->nlbl_state = sksec->nlbl_state;
  337. }
  338. /**
  339. * selinux_netlbl_socket_post_create - Label a socket using NetLabel
  340. * @sock: the socket to label
  341. * @family: protocol family
  342. *
  343. * Description:
  344. * Attempt to label a socket using the NetLabel mechanism using the given
  345. * SID. Returns zero values on success, negative values on failure.
  346. *
  347. */
  348. int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
  349. {
  350. int rc;
  351. struct sk_security_struct *sksec = sk->sk_security;
  352. struct netlbl_lsm_secattr *secattr;
  353. if (family != PF_INET && family != PF_INET6)
  354. return 0;
  355. secattr = selinux_netlbl_sock_genattr(sk);
  356. if (secattr == NULL)
  357. return -ENOMEM;
  358. rc = netlbl_sock_setattr(sk, family, secattr);
  359. switch (rc) {
  360. case 0:
  361. sksec->nlbl_state = NLBL_LABELED;
  362. break;
  363. case -EDESTADDRREQ:
  364. sksec->nlbl_state = NLBL_REQSKB;
  365. rc = 0;
  366. break;
  367. }
  368. return rc;
  369. }
  370. /**
  371. * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
  372. * @sksec: the sock's sk_security_struct
  373. * @skb: the packet
  374. * @family: protocol family
  375. * @ad: the audit data
  376. *
  377. * Description:
  378. * Fetch the NetLabel security attributes from @skb and perform an access check
  379. * against the receiving socket. Returns zero on success, negative values on
  380. * error.
  381. *
  382. */
  383. int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
  384. struct sk_buff *skb,
  385. u16 family,
  386. struct common_audit_data *ad)
  387. {
  388. int rc;
  389. u32 nlbl_sid;
  390. u32 perm;
  391. struct netlbl_lsm_secattr secattr;
  392. if (!netlbl_enabled())
  393. return 0;
  394. netlbl_secattr_init(&secattr);
  395. rc = netlbl_skbuff_getattr(skb, family, &secattr);
  396. if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
  397. rc = selinux_netlbl_sidlookup_cached(skb, family,
  398. &secattr, &nlbl_sid);
  399. else
  400. nlbl_sid = SECINITSID_UNLABELED;
  401. netlbl_secattr_destroy(&secattr);
  402. if (rc != 0)
  403. return rc;
  404. switch (sksec->sclass) {
  405. case SECCLASS_UDP_SOCKET:
  406. perm = UDP_SOCKET__RECVFROM;
  407. break;
  408. case SECCLASS_TCP_SOCKET:
  409. perm = TCP_SOCKET__RECVFROM;
  410. break;
  411. default:
  412. perm = RAWIP_SOCKET__RECVFROM;
  413. }
  414. rc = avc_has_perm(&selinux_state,
  415. sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
  416. if (rc == 0)
  417. return 0;
  418. if (nlbl_sid != SECINITSID_UNLABELED)
  419. netlbl_skbuff_err(skb, family, rc, 0);
  420. return rc;
  421. }
  422. /**
  423. * selinux_netlbl_option - Is this a NetLabel option
  424. * @level: the socket level or protocol
  425. * @optname: the socket option name
  426. *
  427. * Description:
  428. * Returns true if @level and @optname refer to a NetLabel option.
  429. * Helper for selinux_netlbl_socket_setsockopt().
  430. */
  431. static inline int selinux_netlbl_option(int level, int optname)
  432. {
  433. return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
  434. (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
  435. }
  436. /**
  437. * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
  438. * @sock: the socket
  439. * @level: the socket level or protocol
  440. * @optname: the socket option name
  441. *
  442. * Description:
  443. * Check the setsockopt() call and if the user is trying to replace the IP
  444. * options on a socket and a NetLabel is in place for the socket deny the
  445. * access; otherwise allow the access. Returns zero when the access is
  446. * allowed, -EACCES when denied, and other negative values on error.
  447. *
  448. */
  449. int selinux_netlbl_socket_setsockopt(struct socket *sock,
  450. int level,
  451. int optname)
  452. {
  453. int rc = 0;
  454. struct sock *sk = sock->sk;
  455. struct sk_security_struct *sksec = sk->sk_security;
  456. struct netlbl_lsm_secattr secattr;
  457. if (selinux_netlbl_option(level, optname) &&
  458. (sksec->nlbl_state == NLBL_LABELED ||
  459. sksec->nlbl_state == NLBL_CONNLABELED)) {
  460. netlbl_secattr_init(&secattr);
  461. lock_sock(sk);
  462. /* call the netlabel function directly as we want to see the
  463. * on-the-wire label that is assigned via the socket's options
  464. * and not the cached netlabel/lsm attributes */
  465. rc = netlbl_sock_getattr(sk, &secattr);
  466. release_sock(sk);
  467. if (rc == 0)
  468. rc = -EACCES;
  469. else if (rc == -ENOMSG)
  470. rc = 0;
  471. netlbl_secattr_destroy(&secattr);
  472. }
  473. return rc;
  474. }
  475. /**
  476. * selinux_netlbl_socket_connect_helper - Help label a client-side socket on
  477. * connect
  478. * @sk: the socket to label
  479. * @addr: the destination address
  480. *
  481. * Description:
  482. * Attempt to label a connected socket with NetLabel using the given address.
  483. * Returns zero values on success, negative values on failure.
  484. *
  485. */
  486. static int selinux_netlbl_socket_connect_helper(struct sock *sk,
  487. struct sockaddr *addr)
  488. {
  489. int rc;
  490. struct sk_security_struct *sksec = sk->sk_security;
  491. struct netlbl_lsm_secattr *secattr;
  492. /* connected sockets are allowed to disconnect when the address family
  493. * is set to AF_UNSPEC, if that is what is happening we want to reset
  494. * the socket */
  495. if (addr->sa_family == AF_UNSPEC) {
  496. netlbl_sock_delattr(sk);
  497. sksec->nlbl_state = NLBL_REQSKB;
  498. rc = 0;
  499. return rc;
  500. }
  501. secattr = selinux_netlbl_sock_genattr(sk);
  502. if (secattr == NULL) {
  503. rc = -ENOMEM;
  504. return rc;
  505. }
  506. rc = netlbl_conn_setattr(sk, addr, secattr);
  507. if (rc == 0)
  508. sksec->nlbl_state = NLBL_CONNLABELED;
  509. return rc;
  510. }
  511. /**
  512. * selinux_netlbl_socket_connect_locked - Label a client-side socket on
  513. * connect
  514. * @sk: the socket to label
  515. * @addr: the destination address
  516. *
  517. * Description:
  518. * Attempt to label a connected socket that already has the socket locked
  519. * with NetLabel using the given address.
  520. * Returns zero values on success, negative values on failure.
  521. *
  522. */
  523. int selinux_netlbl_socket_connect_locked(struct sock *sk,
  524. struct sockaddr *addr)
  525. {
  526. struct sk_security_struct *sksec = sk->sk_security;
  527. if (sksec->nlbl_state != NLBL_REQSKB &&
  528. sksec->nlbl_state != NLBL_CONNLABELED)
  529. return 0;
  530. return selinux_netlbl_socket_connect_helper(sk, addr);
  531. }
  532. /**
  533. * selinux_netlbl_socket_connect - Label a client-side socket on connect
  534. * @sk: the socket to label
  535. * @addr: the destination address
  536. *
  537. * Description:
  538. * Attempt to label a connected socket with NetLabel using the given address.
  539. * Returns zero values on success, negative values on failure.
  540. *
  541. */
  542. int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
  543. {
  544. int rc;
  545. lock_sock(sk);
  546. rc = selinux_netlbl_socket_connect_locked(sk, addr);
  547. release_sock(sk);
  548. return rc;
  549. }