diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-06 18:39:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-06 18:39:26 -0400 |
commit | 9eda2d2dca830f0f8923b1f377d0fb70f576af1d (patch) | |
tree | 5bdc06d14182e67ebdf20e5543de2a407563662f | |
parent | 6ad11bdd57ad31182850a54235f0e947cbfd5ad0 (diff) | |
parent | 6b6bc6205d98796361962ee282a063f18ba8dc57 (diff) |
Merge tag 'selinux-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull SELinux updates from Paul Moore:
"A bigger than usual pull request for SELinux, 13 patches (lucky!)
along with a scary looking diffstat.
Although if you look a bit closer, excluding the usual minor
tweaks/fixes, there are really only two significant changes in this
pull request: the addition of proper SELinux access controls for SCTP
and the encapsulation of a lot of internal SELinux state.
The SCTP changes are the result of a multi-month effort (maybe even a
year or longer?) between the SELinux folks and the SCTP folks to add
proper SELinux controls. A special thanks go to Richard for seeing
this through and keeping the effort moving forward.
The state encapsulation work is a bit of janitorial work that came out
of some early work on SELinux namespacing. The question of namespacing
is still an open one, but I believe there is some real value in the
encapsulation work so we've split that out and are now sending that up
to you"
* tag 'selinux-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
selinux: wrap AVC state
selinux: wrap selinuxfs state
selinux: fix handling of uninitialized selinux state in get_bools/classes
selinux: Update SELinux SCTP documentation
selinux: Fix ltp test connect-syscall failure
selinux: rename the {is,set}_enforcing() functions
selinux: wrap global selinux state
selinux: fix typo in selinux_netlbl_sctp_sk_clone declaration
selinux: Add SCTP support
sctp: Add LSM hooks
sctp: Add ip option support
security: Add support for SCTP security hooks
netlabel: If PF_INET6, check sk_buff ip header version
43 files changed, 2936 insertions, 1252 deletions
diff --git a/Documentation/security/LSM-sctp.rst b/Documentation/security/LSM-sctp.rst new file mode 100644 index 000000000000..6e5a3925a860 --- /dev/null +++ b/Documentation/security/LSM-sctp.rst | |||
@@ -0,0 +1,175 @@ | |||
1 | SCTP LSM Support | ||
2 | ================ | ||
3 | |||
4 | For security module support, three SCTP specific hooks have been implemented:: | ||
5 | |||
6 | security_sctp_assoc_request() | ||
7 | security_sctp_bind_connect() | ||
8 | security_sctp_sk_clone() | ||
9 | |||
10 | Also the following security hook has been utilised:: | ||
11 | |||
12 | security_inet_conn_established() | ||
13 | |||
14 | The usage of these hooks are described below with the SELinux implementation | ||
15 | described in ``Documentation/security/SELinux-sctp.rst`` | ||
16 | |||
17 | |||
18 | security_sctp_assoc_request() | ||
19 | ----------------------------- | ||
20 | Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the | ||
21 | security module. Returns 0 on success, error on failure. | ||
22 | :: | ||
23 | |||
24 | @ep - pointer to sctp endpoint structure. | ||
25 | @skb - pointer to skbuff of association packet. | ||
26 | |||
27 | |||
28 | security_sctp_bind_connect() | ||
29 | ----------------------------- | ||
30 | Passes one or more ipv4/ipv6 addresses to the security module for validation | ||
31 | based on the ``@optname`` that will result in either a bind or connect | ||
32 | service as shown in the permission check tables below. | ||
33 | Returns 0 on success, error on failure. | ||
34 | :: | ||
35 | |||
36 | @sk - Pointer to sock structure. | ||
37 | @optname - Name of the option to validate. | ||
38 | @address - One or more ipv4 / ipv6 addresses. | ||
39 | @addrlen - The total length of address(s). This is calculated on each | ||
40 | ipv4 or ipv6 address using sizeof(struct sockaddr_in) or | ||
41 | sizeof(struct sockaddr_in6). | ||
42 | |||
43 | ------------------------------------------------------------------ | ||
44 | | BIND Type Checks | | ||
45 | | @optname | @address contains | | ||
46 | |----------------------------|-----------------------------------| | ||
47 | | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses | | ||
48 | | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address | | ||
49 | | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address | | ||
50 | ------------------------------------------------------------------ | ||
51 | |||
52 | ------------------------------------------------------------------ | ||
53 | | CONNECT Type Checks | | ||
54 | | @optname | @address contains | | ||
55 | |----------------------------|-----------------------------------| | ||
56 | | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses | | ||
57 | | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | | ||
58 | | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address | | ||
59 | | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address | | ||
60 | ------------------------------------------------------------------ | ||
61 | |||
62 | A summary of the ``@optname`` entries is as follows:: | ||
63 | |||
64 | SCTP_SOCKOPT_BINDX_ADD - Allows additional bind addresses to be | ||
65 | associated after (optionally) calling | ||
66 | bind(3). | ||
67 | sctp_bindx(3) adds a set of bind | ||
68 | addresses on a socket. | ||
69 | |||
70 | SCTP_SOCKOPT_CONNECTX - Allows the allocation of multiple | ||
71 | addresses for reaching a peer | ||
72 | (multi-homed). | ||
73 | sctp_connectx(3) initiates a connection | ||
74 | on an SCTP socket using multiple | ||
75 | destination addresses. | ||
76 | |||
77 | SCTP_SENDMSG_CONNECT - Initiate a connection that is generated by a | ||
78 | sendmsg(2) or sctp_sendmsg(3) on a new asociation. | ||
79 | |||
80 | SCTP_PRIMARY_ADDR - Set local primary address. | ||
81 | |||
82 | SCTP_SET_PEER_PRIMARY_ADDR - Request peer sets address as | ||
83 | association primary. | ||
84 | |||
85 | SCTP_PARAM_ADD_IP - These are used when Dynamic Address | ||
86 | SCTP_PARAM_SET_PRIMARY - Reconfiguration is enabled as explained below. | ||
87 | |||
88 | |||
89 | To support Dynamic Address Reconfiguration the following parameters must be | ||
90 | enabled on both endpoints (or use the appropriate **setsockopt**\(2)):: | ||
91 | |||
92 | /proc/sys/net/sctp/addip_enable | ||
93 | /proc/sys/net/sctp/addip_noauth_enable | ||
94 | |||
95 | then the following *_PARAM_*'s are sent to the peer in an | ||
96 | ASCONF chunk when the corresponding ``@optname``'s are present:: | ||
97 | |||
98 | @optname ASCONF Parameter | ||
99 | ---------- ------------------ | ||
100 | SCTP_SOCKOPT_BINDX_ADD -> SCTP_PARAM_ADD_IP | ||
101 | SCTP_SET_PEER_PRIMARY_ADDR -> SCTP_PARAM_SET_PRIMARY | ||
102 | |||
103 | |||
104 | security_sctp_sk_clone() | ||
105 | ------------------------- | ||
106 | Called whenever a new socket is created by **accept**\(2) | ||
107 | (i.e. a TCP style socket) or when a socket is 'peeled off' e.g userspace | ||
108 | calls **sctp_peeloff**\(3). | ||
109 | :: | ||
110 | |||
111 | @ep - pointer to current sctp endpoint structure. | ||
112 | @sk - pointer to current sock structure. | ||
113 | @sk - pointer to new sock structure. | ||
114 | |||
115 | |||
116 | security_inet_conn_established() | ||
117 | --------------------------------- | ||
118 | Called when a COOKIE ACK is received:: | ||
119 | |||
120 | @sk - pointer to sock structure. | ||
121 | @skb - pointer to skbuff of the COOKIE ACK packet. | ||
122 | |||
123 | |||
124 | Security Hooks used for Association Establishment | ||
125 | ================================================= | ||
126 | The following diagram shows the use of ``security_sctp_bind_connect()``, | ||
127 | ``security_sctp_assoc_request()``, ``security_inet_conn_established()`` when | ||
128 | establishing an association. | ||
129 | :: | ||
130 | |||
131 | SCTP endpoint "A" SCTP endpoint "Z" | ||
132 | ================= ================= | ||
133 | sctp_sf_do_prm_asoc() | ||
134 | Association setup can be initiated | ||
135 | by a connect(2), sctp_connectx(3), | ||
136 | sendmsg(2) or sctp_sendmsg(3). | ||
137 | These will result in a call to | ||
138 | security_sctp_bind_connect() to | ||
139 | initiate an association to | ||
140 | SCTP peer endpoint "Z". | ||
141 | INIT ---------------------------------------------> | ||
142 | sctp_sf_do_5_1B_init() | ||
143 | Respond to an INIT chunk. | ||
144 | SCTP peer endpoint "A" is | ||
145 | asking for an association. Call | ||
146 | security_sctp_assoc_request() | ||
147 | to set the peer label if first | ||
148 | association. | ||
149 | If not first association, check | ||
150 | whether allowed, IF so send: | ||
151 | <----------------------------------------------- INIT ACK | ||
152 | | ELSE audit event and silently | ||
153 | | discard the packet. | ||
154 | | | ||
155 | COOKIE ECHO ------------------------------------------> | ||
156 | | | ||
157 | | | ||
158 | | | ||
159 | <------------------------------------------- COOKIE ACK | ||
160 | | | | ||
161 | sctp_sf_do_5_1E_ca | | ||
162 | Call security_inet_conn_established() | | ||
163 | to set the peer label. | | ||
164 | | | | ||
165 | | If SCTP_SOCKET_TCP or peeled off | ||
166 | | socket security_sctp_sk_clone() is | ||
167 | | called to clone the new socket. | ||
168 | | | | ||
169 | ESTABLISHED ESTABLISHED | ||
170 | | | | ||
171 | ------------------------------------------------------------------ | ||
172 | | Association Established | | ||
173 | ------------------------------------------------------------------ | ||
174 | |||
175 | |||
diff --git a/Documentation/security/SELinux-sctp.rst b/Documentation/security/SELinux-sctp.rst new file mode 100644 index 000000000000..a332cb1c5334 --- /dev/null +++ b/Documentation/security/SELinux-sctp.rst | |||
@@ -0,0 +1,158 @@ | |||
1 | SCTP SELinux Support | ||
2 | ===================== | ||
3 | |||
4 | Security Hooks | ||
5 | =============== | ||
6 | |||
7 | ``Documentation/security/LSM-sctp.rst`` describes the following SCTP security | ||
8 | hooks with the SELinux specifics expanded below:: | ||
9 | |||
10 | security_sctp_assoc_request() | ||
11 | security_sctp_bind_connect() | ||
12 | security_sctp_sk_clone() | ||
13 | security_inet_conn_established() | ||
14 | |||
15 | |||
16 | security_sctp_assoc_request() | ||
17 | ----------------------------- | ||
18 | Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the | ||
19 | security module. Returns 0 on success, error on failure. | ||
20 | :: | ||
21 | |||
22 | @ep - pointer to sctp endpoint structure. | ||
23 | @skb - pointer to skbuff of association packet. | ||
24 | |||
25 | The security module performs the following operations: | ||
26 | IF this is the first association on ``@ep->base.sk``, then set the peer | ||
27 | sid to that in ``@skb``. This will ensure there is only one peer sid | ||
28 | assigned to ``@ep->base.sk`` that may support multiple associations. | ||
29 | |||
30 | ELSE validate the ``@ep->base.sk peer_sid`` against the ``@skb peer sid`` | ||
31 | to determine whether the association should be allowed or denied. | ||
32 | |||
33 | Set the sctp ``@ep sid`` to socket's sid (from ``ep->base.sk``) with | ||
34 | MLS portion taken from ``@skb peer sid``. This will be used by SCTP | ||
35 | TCP style sockets and peeled off connections as they cause a new socket | ||
36 | to be generated. | ||
37 | |||
38 | If IP security options are configured (CIPSO/CALIPSO), then the ip | ||
39 | options are set on the socket. | ||
40 | |||
41 | |||
42 | security_sctp_bind_connect() | ||
43 | ----------------------------- | ||
44 | Checks permissions required for ipv4/ipv6 addresses based on the ``@optname`` | ||
45 | as follows:: | ||
46 | |||
47 | ------------------------------------------------------------------ | ||
48 | | BIND Permission Checks | | ||
49 | | @optname | @address contains | | ||
50 | |----------------------------|-----------------------------------| | ||
51 | | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses | | ||
52 | | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address | | ||
53 | | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address | | ||
54 | ------------------------------------------------------------------ | ||
55 | |||
56 | ------------------------------------------------------------------ | ||
57 | | CONNECT Permission Checks | | ||
58 | | @optname | @address contains | | ||
59 | |----------------------------|-----------------------------------| | ||
60 | | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses | | ||
61 | | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | | ||
62 | | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address | | ||
63 | | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address | | ||
64 | ------------------------------------------------------------------ | ||
65 | |||
66 | |||
67 | ``Documentation/security/LSM-sctp.rst`` gives a summary of the ``@optname`` | ||
68 | entries and also describes ASCONF chunk processing when Dynamic Address | ||
69 | Reconfiguration is enabled. | ||
70 | |||
71 | |||
72 | security_sctp_sk_clone() | ||
73 | ------------------------- | ||
74 | Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style | ||
75 | socket) or when a socket is 'peeled off' e.g userspace calls | ||
76 | **sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new | ||
77 | sockets sid and peer sid to that contained in the ``@ep sid`` and | ||
78 | ``@ep peer sid`` respectively. | ||
79 | :: | ||
80 | |||
81 | @ep - pointer to current sctp endpoint structure. | ||
82 | @sk - pointer to current sock structure. | ||
83 | @sk - pointer to new sock structure. | ||
84 | |||
85 | |||
86 | security_inet_conn_established() | ||
87 | --------------------------------- | ||
88 | Called when a COOKIE ACK is received where it sets the connection's peer sid | ||
89 | to that in ``@skb``:: | ||
90 | |||
91 | @sk - pointer to sock structure. | ||
92 | @skb - pointer to skbuff of the COOKIE ACK packet. | ||
93 | |||
94 | |||
95 | Policy Statements | ||
96 | ================== | ||
97 | The following class and permissions to support SCTP are available within the | ||
98 | kernel:: | ||
99 | |||
100 | class sctp_socket inherits socket { node_bind } | ||
101 | |||
102 | whenever the following policy capability is enabled:: | ||
103 | |||
104 | policycap extended_socket_class; | ||
105 | |||
106 | SELinux SCTP support adds the ``name_connect`` permission for connecting | ||
107 | to a specific port type and the ``association`` permission that is explained | ||
108 | in the section below. | ||
109 | |||
110 | If userspace tools have been updated, SCTP will support the ``portcon`` | ||
111 | statement as shown in the following example:: | ||
112 | |||
113 | portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0 | ||
114 | |||
115 | |||
116 | SCTP Peer Labeling | ||
117 | =================== | ||
118 | An SCTP socket will only have one peer label assigned to it. This will be | ||
119 | assigned during the establishment of the first association. Any further | ||
120 | associations on this socket will have their packet peer label compared to | ||
121 | the sockets peer label, and only if they are different will the | ||
122 | ``association`` permission be validated. This is validated by checking the | ||
123 | socket peer sid against the received packets peer sid to determine whether | ||
124 | the association should be allowed or denied. | ||
125 | |||
126 | NOTES: | ||
127 | 1) If peer labeling is not enabled, then the peer context will always be | ||
128 | ``SECINITSID_UNLABELED`` (``unlabeled_t`` in Reference Policy). | ||
129 | |||
130 | 2) As SCTP can support more than one transport address per endpoint | ||
131 | (multi-homing) on a single socket, it is possible to configure policy | ||
132 | and NetLabel to provide different peer labels for each of these. As the | ||
133 | socket peer label is determined by the first associations transport | ||
134 | address, it is recommended that all peer labels are consistent. | ||
135 | |||
136 | 3) **getpeercon**\(3) may be used by userspace to retrieve the sockets peer | ||
137 | context. | ||
138 | |||
139 | 4) While not SCTP specific, be aware when using NetLabel that if a label | ||
140 | is assigned to a specific interface, and that interface 'goes down', | ||
141 | then the NetLabel service will remove the entry. Therefore ensure that | ||
142 | the network startup scripts call **netlabelctl**\(8) to set the required | ||
143 | label (see **netlabel-config**\(8) helper script for details). | ||
144 | |||
145 | 5) The NetLabel SCTP peer labeling rules apply as discussed in the following | ||
146 | set of posts tagged "netlabel" at: http://www.paul-moore.com/blog/t. | ||
147 | |||
148 | 6) CIPSO is only supported for IPv4 addressing: ``socket(AF_INET, ...)`` | ||
149 | CALIPSO is only supported for IPv6 addressing: ``socket(AF_INET6, ...)`` | ||
150 | |||
151 | Note the following when testing CIPSO/CALIPSO: | ||
152 | a) CIPSO will send an ICMP packet if an SCTP packet cannot be | ||
153 | delivered because of an invalid label. | ||
154 | b) CALIPSO does not send an ICMP packet, just silently discards it. | ||
155 | |||
156 | 7) IPSEC is not supported as RFC 3554 - sctp/ipsec support has not been | ||
157 | implemented in userspace (**racoon**\(8) or **ipsec_pluto**\(8)), | ||
158 | although the kernel supports SCTP/IPSEC. | ||
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index bde167fa2c51..6e6951b42be5 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
@@ -906,6 +906,33 @@ | |||
906 | * associated with the TUN device's security structure. | 906 | * associated with the TUN device's security structure. |
907 | * @security pointer to the TUN devices's security structure. | 907 | * @security pointer to the TUN devices's security structure. |
908 | * | 908 | * |
909 | * Security hooks for SCTP | ||
910 | * | ||
911 | * @sctp_assoc_request: | ||
912 | * Passes the @ep and @chunk->skb of the association INIT packet to | ||
913 | * the security module. | ||
914 | * @ep pointer to sctp endpoint structure. | ||
915 | * @skb pointer to skbuff of association packet. | ||
916 | * Return 0 on success, error on failure. | ||
917 | * @sctp_bind_connect: | ||
918 | * Validiate permissions required for each address associated with sock | ||
919 | * @sk. Depending on @optname, the addresses will be treated as either | ||
920 | * for a connect or bind service. The @addrlen is calculated on each | ||
921 | * ipv4 and ipv6 address using sizeof(struct sockaddr_in) or | ||
922 | * sizeof(struct sockaddr_in6). | ||
923 | * @sk pointer to sock structure. | ||
924 | * @optname name of the option to validate. | ||
925 | * @address list containing one or more ipv4/ipv6 addresses. | ||
926 | * @addrlen total length of address(s). | ||
927 | * Return 0 on success, error on failure. | ||
928 | * @sctp_sk_clone: | ||
929 | * Called whenever a new socket is created by accept(2) (i.e. a TCP | ||
930 | * style socket) or when a socket is 'peeled off' e.g userspace | ||
931 | * calls sctp_peeloff(3). | ||
932 | * @ep pointer to current sctp endpoint structure. | ||
933 | * @sk pointer to current sock structure. | ||
934 | * @sk pointer to new sock structure. | ||
935 | * | ||
909 | * Security hooks for Infiniband | 936 | * Security hooks for Infiniband |
910 | * | 937 | * |
911 | * @ib_pkey_access: | 938 | * @ib_pkey_access: |
@@ -1665,6 +1692,12 @@ union security_list_options { | |||
1665 | int (*tun_dev_attach_queue)(void *security); | 1692 | int (*tun_dev_attach_queue)(void *security); |
1666 | int (*tun_dev_attach)(struct sock *sk, void *security); | 1693 | int (*tun_dev_attach)(struct sock *sk, void *security); |
1667 | int (*tun_dev_open)(void *security); | 1694 | int (*tun_dev_open)(void *security); |
1695 | int (*sctp_assoc_request)(struct sctp_endpoint *ep, | ||
1696 | struct sk_buff *skb); | ||
1697 | int (*sctp_bind_connect)(struct sock *sk, int optname, | ||
1698 | struct sockaddr *address, int addrlen); | ||
1699 | void (*sctp_sk_clone)(struct sctp_endpoint *ep, struct sock *sk, | ||
1700 | struct sock *newsk); | ||
1668 | #endif /* CONFIG_SECURITY_NETWORK */ | 1701 | #endif /* CONFIG_SECURITY_NETWORK */ |
1669 | 1702 | ||
1670 | #ifdef CONFIG_SECURITY_INFINIBAND | 1703 | #ifdef CONFIG_SECURITY_INFINIBAND |
@@ -1914,6 +1947,9 @@ struct security_hook_heads { | |||
1914 | struct list_head tun_dev_attach_queue; | 1947 | struct list_head tun_dev_attach_queue; |
1915 | struct list_head tun_dev_attach; | 1948 | struct list_head tun_dev_attach; |
1916 | struct list_head tun_dev_open; | 1949 | struct list_head tun_dev_open; |
1950 | struct list_head sctp_assoc_request; | ||
1951 | struct list_head sctp_bind_connect; | ||
1952 | struct list_head sctp_sk_clone; | ||
1917 | #endif /* CONFIG_SECURITY_NETWORK */ | 1953 | #endif /* CONFIG_SECURITY_NETWORK */ |
1918 | #ifdef CONFIG_SECURITY_INFINIBAND | 1954 | #ifdef CONFIG_SECURITY_INFINIBAND |
1919 | struct list_head ib_pkey_access; | 1955 | struct list_head ib_pkey_access; |
diff --git a/include/linux/security.h b/include/linux/security.h index 128e1e4a5346..17ffd1ef6074 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -112,6 +112,7 @@ struct xfrm_policy; | |||
112 | struct xfrm_state; | 112 | struct xfrm_state; |
113 | struct xfrm_user_sec_ctx; | 113 | struct xfrm_user_sec_ctx; |
114 | struct seq_file; | 114 | struct seq_file; |
115 | struct sctp_endpoint; | ||
115 | 116 | ||
116 | #ifdef CONFIG_MMU | 117 | #ifdef CONFIG_MMU |
117 | extern unsigned long mmap_min_addr; | 118 | extern unsigned long mmap_min_addr; |
@@ -1226,6 +1227,11 @@ int security_tun_dev_create(void); | |||
1226 | int security_tun_dev_attach_queue(void *security); | 1227 | int security_tun_dev_attach_queue(void *security); |
1227 | int security_tun_dev_attach(struct sock *sk, void *security); | 1228 | int security_tun_dev_attach(struct sock *sk, void *security); |
1228 | int security_tun_dev_open(void *security); | 1229 | int security_tun_dev_open(void *security); |
1230 | int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb); | ||
1231 | int security_sctp_bind_connect(struct sock *sk, int optname, | ||
1232 | struct sockaddr *address, int addrlen); | ||
1233 | void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, | ||
1234 | struct sock *newsk); | ||
1229 | 1235 | ||
1230 | #else /* CONFIG_SECURITY_NETWORK */ | 1236 | #else /* CONFIG_SECURITY_NETWORK */ |
1231 | static inline int security_unix_stream_connect(struct sock *sock, | 1237 | static inline int security_unix_stream_connect(struct sock *sock, |
@@ -1418,6 +1424,25 @@ static inline int security_tun_dev_open(void *security) | |||
1418 | { | 1424 | { |
1419 | return 0; | 1425 | return 0; |
1420 | } | 1426 | } |
1427 | |||
1428 | static inline int security_sctp_assoc_request(struct sctp_endpoint *ep, | ||
1429 | struct sk_buff *skb) | ||
1430 | { | ||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | static inline int security_sctp_bind_connect(struct sock *sk, int optname, | ||
1435 | struct sockaddr *address, | ||
1436 | int addrlen) | ||
1437 | { | ||
1438 | return 0; | ||
1439 | } | ||
1440 | |||
1441 | static inline void security_sctp_sk_clone(struct sctp_endpoint *ep, | ||
1442 | struct sock *sk, | ||
1443 | struct sock *newsk) | ||
1444 | { | ||
1445 | } | ||
1421 | #endif /* CONFIG_SECURITY_NETWORK */ | 1446 | #endif /* CONFIG_SECURITY_NETWORK */ |
1422 | 1447 | ||
1423 | #ifdef CONFIG_SECURITY_INFINIBAND | 1448 | #ifdef CONFIG_SECURITY_INFINIBAND |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 72c5b8fc3232..28b996d63490 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -432,9 +432,11 @@ static inline int sctp_list_single_entry(struct list_head *head) | |||
432 | static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu) | 432 | static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu) |
433 | { | 433 | { |
434 | struct sctp_sock *sp = sctp_sk(asoc->base.sk); | 434 | struct sctp_sock *sp = sctp_sk(asoc->base.sk); |
435 | struct sctp_af *af = sp->pf->af; | ||
435 | int frag = pmtu; | 436 | int frag = pmtu; |
436 | 437 | ||
437 | frag -= sp->pf->af->net_header_len; | 438 | frag -= af->ip_options_len(asoc->base.sk); |
439 | frag -= af->net_header_len; | ||
438 | frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream); | 440 | frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream); |
439 | 441 | ||
440 | if (asoc->user_frag) | 442 | if (asoc->user_frag) |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c63249ea34c3..a0ec462bc1a9 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -491,6 +491,7 @@ struct sctp_af { | |||
491 | void (*ecn_capable)(struct sock *sk); | 491 | void (*ecn_capable)(struct sock *sk); |
492 | __u16 net_header_len; | 492 | __u16 net_header_len; |
493 | int sockaddr_len; | 493 | int sockaddr_len; |
494 | int (*ip_options_len)(struct sock *sk); | ||
494 | sa_family_t sa_family; | 495 | sa_family_t sa_family; |
495 | struct list_head list; | 496 | struct list_head list; |
496 | }; | 497 | }; |
@@ -515,6 +516,7 @@ struct sctp_pf { | |||
515 | int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr); | 516 | int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr); |
516 | void (*to_sk_saddr)(union sctp_addr *, struct sock *sk); | 517 | void (*to_sk_saddr)(union sctp_addr *, struct sock *sk); |
517 | void (*to_sk_daddr)(union sctp_addr *, struct sock *sk); | 518 | void (*to_sk_daddr)(union sctp_addr *, struct sock *sk); |
519 | void (*copy_ip_options)(struct sock *sk, struct sock *newsk); | ||
518 | struct sctp_af *af; | 520 | struct sctp_af *af; |
519 | }; | 521 | }; |
520 | 522 | ||
@@ -1320,6 +1322,16 @@ struct sctp_endpoint { | |||
1320 | reconf_enable:1; | 1322 | reconf_enable:1; |
1321 | 1323 | ||
1322 | __u8 strreset_enable; | 1324 | __u8 strreset_enable; |
1325 | |||
1326 | /* Security identifiers from incoming (INIT). These are set by | ||
1327 | * security_sctp_assoc_request(). These will only be used by | ||
1328 | * SCTP TCP type sockets and peeled off connections as they | ||
1329 | * cause a new socket to be generated. security_sctp_sk_clone() | ||
1330 | * will then plug these into the new socket. | ||
1331 | */ | ||
1332 | |||
1333 | u32 secid; | ||
1334 | u32 peer_secid; | ||
1323 | }; | 1335 | }; |
1324 | 1336 | ||
1325 | /* Recover the outter endpoint structure. */ | 1337 | /* Recover the outter endpoint structure. */ |
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index afd4346386e0..b64d583bf053 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h | |||
@@ -127,6 +127,7 @@ typedef __s32 sctp_assoc_t; | |||
127 | #define SCTP_STREAM_SCHEDULER 123 | 127 | #define SCTP_STREAM_SCHEDULER 123 |
128 | #define SCTP_STREAM_SCHEDULER_VALUE 124 | 128 | #define SCTP_STREAM_SCHEDULER_VALUE 124 |
129 | #define SCTP_INTERLEAVING_SUPPORTED 125 | 129 | #define SCTP_INTERLEAVING_SUPPORTED 125 |
130 | #define SCTP_SENDMSG_CONNECT 126 | ||
130 | 131 | ||
131 | /* PR-SCTP policies */ | 132 | /* PR-SCTP policies */ |
132 | #define SCTP_PR_SCTP_NONE 0x0000 | 133 | #define SCTP_PR_SCTP_NONE 0x0000 |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 22dc1b9d6362..c070dfc0190a 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -1472,6 +1472,16 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, | |||
1472 | iface = rcu_dereference(netlbl_unlhsh_def); | 1472 | iface = rcu_dereference(netlbl_unlhsh_def); |
1473 | if (iface == NULL || !iface->valid) | 1473 | if (iface == NULL || !iface->valid) |
1474 | goto unlabel_getattr_nolabel; | 1474 | goto unlabel_getattr_nolabel; |
1475 | |||
1476 | #if IS_ENABLED(CONFIG_IPV6) | ||
1477 | /* When resolving a fallback label, check the sk_buff version as | ||
1478 | * it is possible (e.g. SCTP) to have family = PF_INET6 while | ||
1479 | * receiving ip_hdr(skb)->version = 4. | ||
1480 | */ | ||
1481 | if (family == PF_INET6 && ip_hdr(skb)->version == 4) | ||
1482 | family = PF_INET; | ||
1483 | #endif /* IPv6 */ | ||
1484 | |||
1475 | switch (family) { | 1485 | switch (family) { |
1476 | case PF_INET: { | 1486 | case PF_INET: { |
1477 | struct iphdr *hdr4; | 1487 | struct iphdr *hdr4; |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index f889a84f264d..be296d633e95 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -172,6 +172,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
172 | struct list_head *pos, *temp; | 172 | struct list_head *pos, *temp; |
173 | struct sctp_chunk *chunk; | 173 | struct sctp_chunk *chunk; |
174 | struct sctp_datamsg *msg; | 174 | struct sctp_datamsg *msg; |
175 | struct sctp_sock *sp; | ||
176 | struct sctp_af *af; | ||
175 | int err; | 177 | int err; |
176 | 178 | ||
177 | msg = sctp_datamsg_new(GFP_KERNEL); | 179 | msg = sctp_datamsg_new(GFP_KERNEL); |
@@ -190,9 +192,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
190 | /* This is the biggest possible DATA chunk that can fit into | 192 | /* This is the biggest possible DATA chunk that can fit into |
191 | * the packet | 193 | * the packet |
192 | */ | 194 | */ |
193 | max_data = asoc->pathmtu - | 195 | sp = sctp_sk(asoc->base.sk); |
194 | sctp_sk(asoc->base.sk)->pf->af->net_header_len - | 196 | af = sp->pf->af; |
195 | sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream); | 197 | max_data = asoc->pathmtu - af->net_header_len - |
198 | sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) - | ||
199 | af->ip_options_len(asoc->base.sk); | ||
196 | max_data = SCTP_TRUNC4(max_data); | 200 | max_data = SCTP_TRUNC4(max_data); |
197 | 201 | ||
198 | /* If the the peer requested that we authenticate DATA chunks | 202 | /* If the the peer requested that we authenticate DATA chunks |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 0d873c58e516..6dd976c8ab61 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
427 | rcu_read_unlock(); | 427 | rcu_read_unlock(); |
428 | } | 428 | } |
429 | 429 | ||
430 | /* Copy over any ip options */ | ||
431 | static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk) | ||
432 | { | ||
433 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | ||
434 | struct ipv6_txoptions *opt; | ||
435 | |||
436 | newnp = inet6_sk(newsk); | ||
437 | |||
438 | rcu_read_lock(); | ||
439 | opt = rcu_dereference(np->opt); | ||
440 | if (opt) { | ||
441 | opt = ipv6_dup_options(newsk, opt); | ||
442 | if (!opt) | ||
443 | pr_err("%s: Failed to copy ip options\n", __func__); | ||
444 | } | ||
445 | RCU_INIT_POINTER(newnp->opt, opt); | ||
446 | rcu_read_unlock(); | ||
447 | } | ||
448 | |||
449 | /* Account for the IP options */ | ||
450 | static int sctp_v6_ip_options_len(struct sock *sk) | ||
451 | { | ||
452 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
453 | struct ipv6_txoptions *opt; | ||
454 | int len = 0; | ||
455 | |||
456 | rcu_read_lock(); | ||
457 | opt = rcu_dereference(np->opt); | ||
458 | if (opt) | ||
459 | len = opt->opt_flen + opt->opt_nflen; | ||
460 | |||
461 | rcu_read_unlock(); | ||
462 | return len; | ||
463 | } | ||
464 | |||
430 | /* Initialize a sockaddr_storage from in incoming skb. */ | 465 | /* Initialize a sockaddr_storage from in incoming skb. */ |
431 | static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb, | 466 | static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb, |
432 | int is_saddr) | 467 | int is_saddr) |
@@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
666 | struct sock *newsk; | 701 | struct sock *newsk; |
667 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 702 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
668 | struct sctp6_sock *newsctp6sk; | 703 | struct sctp6_sock *newsctp6sk; |
669 | struct ipv6_txoptions *opt; | ||
670 | 704 | ||
671 | newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern); | 705 | newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern); |
672 | if (!newsk) | 706 | if (!newsk) |
@@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
689 | newnp->ipv6_ac_list = NULL; | 723 | newnp->ipv6_ac_list = NULL; |
690 | newnp->ipv6_fl_list = NULL; | 724 | newnp->ipv6_fl_list = NULL; |
691 | 725 | ||
692 | rcu_read_lock(); | 726 | sctp_v6_copy_ip_options(sk, newsk); |
693 | opt = rcu_dereference(np->opt); | ||
694 | if (opt) | ||
695 | opt = ipv6_dup_options(newsk, opt); | ||
696 | RCU_INIT_POINTER(newnp->opt, opt); | ||
697 | rcu_read_unlock(); | ||
698 | 727 | ||
699 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() | 728 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() |
700 | * and getpeername(). | 729 | * and getpeername(). |
@@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = { | |||
1041 | .ecn_capable = sctp_v6_ecn_capable, | 1070 | .ecn_capable = sctp_v6_ecn_capable, |
1042 | .net_header_len = sizeof(struct ipv6hdr), | 1071 | .net_header_len = sizeof(struct ipv6hdr), |
1043 | .sockaddr_len = sizeof(struct sockaddr_in6), | 1072 | .sockaddr_len = sizeof(struct sockaddr_in6), |
1073 | .ip_options_len = sctp_v6_ip_options_len, | ||
1044 | #ifdef CONFIG_COMPAT | 1074 | #ifdef CONFIG_COMPAT |
1045 | .compat_setsockopt = compat_ipv6_setsockopt, | 1075 | .compat_setsockopt = compat_ipv6_setsockopt, |
1046 | .compat_getsockopt = compat_ipv6_getsockopt, | 1076 | .compat_getsockopt = compat_ipv6_getsockopt, |
@@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = { | |||
1059 | .addr_to_user = sctp_v6_addr_to_user, | 1089 | .addr_to_user = sctp_v6_addr_to_user, |
1060 | .to_sk_saddr = sctp_v6_to_sk_saddr, | 1090 | .to_sk_saddr = sctp_v6_to_sk_saddr, |
1061 | .to_sk_daddr = sctp_v6_to_sk_daddr, | 1091 | .to_sk_daddr = sctp_v6_to_sk_daddr, |
1092 | .copy_ip_options = sctp_v6_copy_ip_options, | ||
1062 | .af = &sctp_af_inet6, | 1093 | .af = &sctp_af_inet6, |
1063 | }; | 1094 | }; |
1064 | 1095 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index d6e1c90cc09a..690d8557bb7b 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet, | |||
69 | 69 | ||
70 | static void sctp_packet_reset(struct sctp_packet *packet) | 70 | static void sctp_packet_reset(struct sctp_packet *packet) |
71 | { | 71 | { |
72 | /* sctp_packet_transmit() relies on this to reset size to the | ||
73 | * current overhead after sending packets. | ||
74 | */ | ||
72 | packet->size = packet->overhead; | 75 | packet->size = packet->overhead; |
76 | |||
73 | packet->has_cookie_echo = 0; | 77 | packet->has_cookie_echo = 0; |
74 | packet->has_sack = 0; | 78 | packet->has_sack = 0; |
75 | packet->has_data = 0; | 79 | packet->has_data = 0; |
@@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag, | |||
87 | struct sctp_transport *tp = packet->transport; | 91 | struct sctp_transport *tp = packet->transport; |
88 | struct sctp_association *asoc = tp->asoc; | 92 | struct sctp_association *asoc = tp->asoc; |
89 | struct sock *sk; | 93 | struct sock *sk; |
94 | size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr); | ||
90 | 95 | ||
91 | pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); | 96 | pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); |
92 | packet->vtag = vtag; | 97 | packet->vtag = vtag; |
@@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag, | |||
95 | if (!sctp_packet_empty(packet)) | 100 | if (!sctp_packet_empty(packet)) |
96 | return; | 101 | return; |
97 | 102 | ||
98 | /* set packet max_size with pathmtu */ | 103 | /* set packet max_size with pathmtu, then calculate overhead */ |
99 | packet->max_size = tp->pathmtu; | 104 | packet->max_size = tp->pathmtu; |
100 | if (!asoc) | 105 | if (asoc) { |
106 | struct sctp_sock *sp = sctp_sk(asoc->base.sk); | ||
107 | struct sctp_af *af = sp->pf->af; | ||
108 | |||
109 | overhead = af->net_header_len + | ||
110 | af->ip_options_len(asoc->base.sk); | ||
111 | overhead += sizeof(struct sctphdr); | ||
112 | packet->overhead = overhead; | ||
113 | packet->size = overhead; | ||
114 | } else { | ||
115 | packet->overhead = overhead; | ||
116 | packet->size = overhead; | ||
101 | return; | 117 | return; |
118 | } | ||
102 | 119 | ||
103 | /* update dst or transport pathmtu if in need */ | 120 | /* update dst or transport pathmtu if in need */ |
104 | sk = asoc->base.sk; | 121 | sk = asoc->base.sk; |
@@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet, | |||
140 | struct sctp_transport *transport, | 157 | struct sctp_transport *transport, |
141 | __u16 sport, __u16 dport) | 158 | __u16 sport, __u16 dport) |
142 | { | 159 | { |
143 | struct sctp_association *asoc = transport->asoc; | ||
144 | size_t overhead; | ||
145 | |||
146 | pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport); | 160 | pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport); |
147 | 161 | ||
148 | packet->transport = transport; | 162 | packet->transport = transport; |
149 | packet->source_port = sport; | 163 | packet->source_port = sport; |
150 | packet->destination_port = dport; | 164 | packet->destination_port = dport; |
151 | INIT_LIST_HEAD(&packet->chunk_list); | 165 | INIT_LIST_HEAD(&packet->chunk_list); |
152 | if (asoc) { | 166 | /* The overhead will be calculated by sctp_packet_config() */ |
153 | struct sctp_sock *sp = sctp_sk(asoc->base.sk); | 167 | packet->overhead = 0; |
154 | overhead = sp->pf->af->net_header_len; | ||
155 | } else { | ||
156 | overhead = sizeof(struct ipv6hdr); | ||
157 | } | ||
158 | overhead += sizeof(struct sctphdr); | ||
159 | packet->overhead = overhead; | ||
160 | sctp_packet_reset(packet); | 168 | sctp_packet_reset(packet); |
161 | packet->vtag = 0; | 169 | packet->vtag = 0; |
162 | } | 170 | } |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a24cde236330..d685f8456762 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -187,6 +187,45 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, | |||
187 | return error; | 187 | return error; |
188 | } | 188 | } |
189 | 189 | ||
190 | /* Copy over any ip options */ | ||
191 | static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk) | ||
192 | { | ||
193 | struct inet_sock *newinet, *inet = inet_sk(sk); | ||
194 | struct ip_options_rcu *inet_opt, *newopt = NULL; | ||
195 | |||
196 | newinet = inet_sk(newsk); | ||
197 | |||
198 | rcu_read_lock(); | ||
199 | inet_opt = rcu_dereference(inet->inet_opt); | ||
200 | if (inet_opt) { | ||
201 | newopt = sock_kmalloc(newsk, sizeof(*inet_opt) + | ||
202 | inet_opt->opt.optlen, GFP_ATOMIC); | ||
203 | if (newopt) | ||
204 | memcpy(newopt, inet_opt, sizeof(*inet_opt) + | ||
205 | inet_opt->opt.optlen); | ||
206 | else | ||
207 | pr_err("%s: Failed to copy ip options\n", __func__); | ||
208 | } | ||
209 | RCU_INIT_POINTER(newinet->inet_opt, newopt); | ||
210 | rcu_read_unlock(); | ||
211 | } | ||
212 | |||
213 | /* Account for the IP options */ | ||
214 | static int sctp_v4_ip_options_len(struct sock *sk) | ||
215 | { | ||
216 | struct inet_sock *inet = inet_sk(sk); | ||
217 | struct ip_options_rcu *inet_opt; | ||
218 | int len = 0; | ||
219 | |||
220 | rcu_read_lock(); | ||
221 | inet_opt = rcu_dereference(inet->inet_opt); | ||
222 | if (inet_opt) | ||
223 | len = inet_opt->opt.optlen; | ||
224 | |||
225 | rcu_read_unlock(); | ||
226 | return len; | ||
227 | } | ||
228 | |||
190 | /* Initialize a sctp_addr from in incoming skb. */ | 229 | /* Initialize a sctp_addr from in incoming skb. */ |
191 | static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, | 230 | static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, |
192 | int is_saddr) | 231 | int is_saddr) |
@@ -538,6 +577,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk, | |||
538 | sctp_copy_sock(newsk, sk, asoc); | 577 | sctp_copy_sock(newsk, sk, asoc); |
539 | sock_reset_flag(newsk, SOCK_ZAPPED); | 578 | sock_reset_flag(newsk, SOCK_ZAPPED); |
540 | 579 | ||
580 | sctp_v4_copy_ip_options(sk, newsk); | ||
581 | |||
541 | newinet = inet_sk(newsk); | 582 | newinet = inet_sk(newsk); |
542 | 583 | ||
543 | newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; | 584 | newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; |
@@ -956,6 +997,7 @@ static struct sctp_pf sctp_pf_inet = { | |||
956 | .addr_to_user = sctp_v4_addr_to_user, | 997 | .addr_to_user = sctp_v4_addr_to_user, |
957 | .to_sk_saddr = sctp_v4_to_sk_saddr, | 998 | .to_sk_saddr = sctp_v4_to_sk_saddr, |
958 | .to_sk_daddr = sctp_v4_to_sk_daddr, | 999 | .to_sk_daddr = sctp_v4_to_sk_daddr, |
1000 | .copy_ip_options = sctp_v4_copy_ip_options, | ||
959 | .af = &sctp_af_inet | 1001 | .af = &sctp_af_inet |
960 | }; | 1002 | }; |
961 | 1003 | ||
@@ -1040,6 +1082,7 @@ static struct sctp_af sctp_af_inet = { | |||
1040 | .ecn_capable = sctp_v4_ecn_capable, | 1082 | .ecn_capable = sctp_v4_ecn_capable, |
1041 | .net_header_len = sizeof(struct iphdr), | 1083 | .net_header_len = sizeof(struct iphdr), |
1042 | .sockaddr_len = sizeof(struct sockaddr_in), | 1084 | .sockaddr_len = sizeof(struct sockaddr_in), |
1085 | .ip_options_len = sctp_v4_ip_options_len, | ||
1043 | #ifdef CONFIG_COMPAT | 1086 | #ifdef CONFIG_COMPAT |
1044 | .compat_setsockopt = compat_ip_setsockopt, | 1087 | .compat_setsockopt = compat_ip_setsockopt, |
1045 | .compat_getsockopt = compat_ip_getsockopt, | 1088 | .compat_getsockopt = compat_ip_getsockopt, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index cc20bc39ee7c..5a4fb1dc8400 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -3098,6 +3098,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
3098 | if (af->is_any(&addr)) | 3098 | if (af->is_any(&addr)) |
3099 | memcpy(&addr, &asconf->source, sizeof(addr)); | 3099 | memcpy(&addr, &asconf->source, sizeof(addr)); |
3100 | 3100 | ||
3101 | if (security_sctp_bind_connect(asoc->ep->base.sk, | ||
3102 | SCTP_PARAM_ADD_IP, | ||
3103 | (struct sockaddr *)&addr, | ||
3104 | af->sockaddr_len)) | ||
3105 | return SCTP_ERROR_REQ_REFUSED; | ||
3106 | |||
3101 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address | 3107 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address |
3102 | * request and does not have the local resources to add this | 3108 | * request and does not have the local resources to add this |
3103 | * new address to the association, it MUST return an Error | 3109 | * new address to the association, it MUST return an Error |
@@ -3164,6 +3170,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
3164 | if (af->is_any(&addr)) | 3170 | if (af->is_any(&addr)) |
3165 | memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); | 3171 | memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); |
3166 | 3172 | ||
3173 | if (security_sctp_bind_connect(asoc->ep->base.sk, | ||
3174 | SCTP_PARAM_SET_PRIMARY, | ||
3175 | (struct sockaddr *)&addr, | ||
3176 | af->sockaddr_len)) | ||
3177 | return SCTP_ERROR_REQ_REFUSED; | ||
3178 | |||
3167 | peer = sctp_assoc_lookup_paddr(asoc, &addr); | 3179 | peer = sctp_assoc_lookup_paddr(asoc, &addr); |
3168 | if (!peer) | 3180 | if (!peer) |
3169 | return SCTP_ERROR_DNS_FAILED; | 3181 | return SCTP_ERROR_DNS_FAILED; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index cc56a67dbb4d..dd0594a10961 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -321,6 +321,11 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, | |||
321 | struct sctp_packet *packet; | 321 | struct sctp_packet *packet; |
322 | int len; | 322 | int len; |
323 | 323 | ||
324 | /* Update socket peer label if first association. */ | ||
325 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
326 | chunk->skb)) | ||
327 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
328 | |||
324 | /* 6.10 Bundling | 329 | /* 6.10 Bundling |
325 | * An endpoint MUST NOT bundle INIT, INIT ACK or | 330 | * An endpoint MUST NOT bundle INIT, INIT ACK or |
326 | * SHUTDOWN COMPLETE with any other chunks. | 331 | * SHUTDOWN COMPLETE with any other chunks. |
@@ -922,6 +927,9 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net, | |||
922 | */ | 927 | */ |
923 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | 928 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
924 | 929 | ||
930 | /* Set peer label for connection. */ | ||
931 | security_inet_conn_established(ep->base.sk, chunk->skb); | ||
932 | |||
925 | /* RFC 2960 5.1 Normal Establishment of an Association | 933 | /* RFC 2960 5.1 Normal Establishment of an Association |
926 | * | 934 | * |
927 | * E) Upon reception of the COOKIE ACK, endpoint "A" will move | 935 | * E) Upon reception of the COOKIE ACK, endpoint "A" will move |
@@ -1459,6 +1467,11 @@ static enum sctp_disposition sctp_sf_do_unexpected_init( | |||
1459 | struct sctp_packet *packet; | 1467 | struct sctp_packet *packet; |
1460 | int len; | 1468 | int len; |
1461 | 1469 | ||
1470 | /* Update socket peer label if first association. */ | ||
1471 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
1472 | chunk->skb)) | ||
1473 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
1474 | |||
1462 | /* 6.10 Bundling | 1475 | /* 6.10 Bundling |
1463 | * An endpoint MUST NOT bundle INIT, INIT ACK or | 1476 | * An endpoint MUST NOT bundle INIT, INIT ACK or |
1464 | * SHUTDOWN COMPLETE with any other chunks. | 1477 | * SHUTDOWN COMPLETE with any other chunks. |
@@ -2145,6 +2158,11 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook( | |||
2145 | } | 2158 | } |
2146 | } | 2159 | } |
2147 | 2160 | ||
2161 | /* Update socket peer label if first association. */ | ||
2162 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
2163 | chunk->skb)) | ||
2164 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
2165 | |||
2148 | /* Set temp so that it won't be added into hashtable */ | 2166 | /* Set temp so that it won't be added into hashtable */ |
2149 | new_asoc->temp = 1; | 2167 | new_asoc->temp = 1; |
2150 | 2168 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7a10ae3c3d82..2a2e094560de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1046,6 +1046,12 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1046 | /* Do the work. */ | 1046 | /* Do the work. */ |
1047 | switch (op) { | 1047 | switch (op) { |
1048 | case SCTP_BINDX_ADD_ADDR: | 1048 | case SCTP_BINDX_ADD_ADDR: |
1049 | /* Allow security module to validate bindx addresses. */ | ||
1050 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD, | ||
1051 | (struct sockaddr *)kaddrs, | ||
1052 | addrs_size); | ||
1053 | if (err) | ||
1054 | goto out; | ||
1049 | err = sctp_bindx_add(sk, kaddrs, addrcnt); | 1055 | err = sctp_bindx_add(sk, kaddrs, addrcnt); |
1050 | if (err) | 1056 | if (err) |
1051 | goto out; | 1057 | goto out; |
@@ -1255,6 +1261,7 @@ static int __sctp_connect(struct sock *sk, | |||
1255 | 1261 | ||
1256 | if (assoc_id) | 1262 | if (assoc_id) |
1257 | *assoc_id = asoc->assoc_id; | 1263 | *assoc_id = asoc->assoc_id; |
1264 | |||
1258 | err = sctp_wait_for_connect(asoc, &timeo); | 1265 | err = sctp_wait_for_connect(asoc, &timeo); |
1259 | /* Note: the asoc may be freed after the return of | 1266 | /* Note: the asoc may be freed after the return of |
1260 | * sctp_wait_for_connect. | 1267 | * sctp_wait_for_connect. |
@@ -1350,7 +1357,16 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1350 | if (unlikely(IS_ERR(kaddrs))) | 1357 | if (unlikely(IS_ERR(kaddrs))) |
1351 | return PTR_ERR(kaddrs); | 1358 | return PTR_ERR(kaddrs); |
1352 | 1359 | ||
1360 | /* Allow security module to validate connectx addresses. */ | ||
1361 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX, | ||
1362 | (struct sockaddr *)kaddrs, | ||
1363 | addrs_size); | ||
1364 | if (err) | ||
1365 | goto out_free; | ||
1366 | |||
1353 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); | 1367 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1368 | |||
1369 | out_free: | ||
1354 | kvfree(kaddrs); | 1370 | kvfree(kaddrs); |
1355 | 1371 | ||
1356 | return err; | 1372 | return err; |
@@ -1680,6 +1696,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, | |||
1680 | struct sctp_association *asoc; | 1696 | struct sctp_association *asoc; |
1681 | enum sctp_scope scope; | 1697 | enum sctp_scope scope; |
1682 | struct cmsghdr *cmsg; | 1698 | struct cmsghdr *cmsg; |
1699 | struct sctp_af *af; | ||
1683 | int err; | 1700 | int err; |
1684 | 1701 | ||
1685 | *tp = NULL; | 1702 | *tp = NULL; |
@@ -1705,6 +1722,21 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, | |||
1705 | 1722 | ||
1706 | scope = sctp_scope(daddr); | 1723 | scope = sctp_scope(daddr); |
1707 | 1724 | ||
1725 | /* Label connection socket for first association 1-to-many | ||
1726 | * style for client sequence socket()->sendmsg(). This | ||
1727 | * needs to be done before sctp_assoc_add_peer() as that will | ||
1728 | * set up the initial packet that needs to account for any | ||
1729 | * security ip options (CIPSO/CALIPSO) added to the packet. | ||
1730 | */ | ||
1731 | af = sctp_get_af_specific(daddr->sa.sa_family); | ||
1732 | if (!af) | ||
1733 | return -EINVAL; | ||
1734 | err = security_sctp_bind_connect(sk, SCTP_SENDMSG_CONNECT, | ||
1735 | (struct sockaddr *)daddr, | ||
1736 | af->sockaddr_len); | ||
1737 | if (err < 0) | ||
1738 | return err; | ||
1739 | |||
1708 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | 1740 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
1709 | if (!asoc) | 1741 | if (!asoc) |
1710 | return -ENOMEM; | 1742 | return -ENOMEM; |
@@ -2932,6 +2964,8 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2932 | { | 2964 | { |
2933 | struct sctp_prim prim; | 2965 | struct sctp_prim prim; |
2934 | struct sctp_transport *trans; | 2966 | struct sctp_transport *trans; |
2967 | struct sctp_af *af; | ||
2968 | int err; | ||
2935 | 2969 | ||
2936 | if (optlen != sizeof(struct sctp_prim)) | 2970 | if (optlen != sizeof(struct sctp_prim)) |
2937 | return -EINVAL; | 2971 | return -EINVAL; |
@@ -2939,6 +2973,17 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2939 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) | 2973 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) |
2940 | return -EFAULT; | 2974 | return -EFAULT; |
2941 | 2975 | ||
2976 | /* Allow security module to validate address but need address len. */ | ||
2977 | af = sctp_get_af_specific(prim.ssp_addr.ss_family); | ||
2978 | if (!af) | ||
2979 | return -EINVAL; | ||
2980 | |||
2981 | err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR, | ||
2982 | (struct sockaddr *)&prim.ssp_addr, | ||
2983 | af->sockaddr_len); | ||
2984 | if (err) | ||
2985 | return err; | ||
2986 | |||
2942 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); | 2987 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); |
2943 | if (!trans) | 2988 | if (!trans) |
2944 | return -EINVAL; | 2989 | return -EINVAL; |
@@ -3161,6 +3206,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign | |||
3161 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) | 3206 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) |
3162 | { | 3207 | { |
3163 | struct sctp_sock *sp = sctp_sk(sk); | 3208 | struct sctp_sock *sp = sctp_sk(sk); |
3209 | struct sctp_af *af = sp->pf->af; | ||
3164 | struct sctp_assoc_value params; | 3210 | struct sctp_assoc_value params; |
3165 | struct sctp_association *asoc; | 3211 | struct sctp_association *asoc; |
3166 | int val; | 3212 | int val; |
@@ -3185,7 +3231,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned | |||
3185 | if (val) { | 3231 | if (val) { |
3186 | int min_len, max_len; | 3232 | int min_len, max_len; |
3187 | 3233 | ||
3188 | min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len; | 3234 | min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len; |
3235 | min_len -= af->ip_options_len(sk); | ||
3189 | min_len -= sizeof(struct sctphdr) + | 3236 | min_len -= sizeof(struct sctphdr) + |
3190 | sizeof(struct sctp_data_chunk); | 3237 | sizeof(struct sctp_data_chunk); |
3191 | 3238 | ||
@@ -3198,7 +3245,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned | |||
3198 | asoc = sctp_id2assoc(sk, params.assoc_id); | 3245 | asoc = sctp_id2assoc(sk, params.assoc_id); |
3199 | if (asoc) { | 3246 | if (asoc) { |
3200 | if (val == 0) { | 3247 | if (val == 0) { |
3201 | val = asoc->pathmtu - sp->pf->af->net_header_len; | 3248 | val = asoc->pathmtu - af->net_header_len; |
3249 | val -= af->ip_options_len(sk); | ||
3202 | val -= sizeof(struct sctphdr) + | 3250 | val -= sizeof(struct sctphdr) + |
3203 | sctp_datachk_len(&asoc->stream); | 3251 | sctp_datachk_len(&asoc->stream); |
3204 | } | 3252 | } |
@@ -3267,6 +3315,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
3267 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) | 3315 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) |
3268 | return -EADDRNOTAVAIL; | 3316 | return -EADDRNOTAVAIL; |
3269 | 3317 | ||
3318 | /* Allow security module to validate address. */ | ||
3319 | err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR, | ||
3320 | (struct sockaddr *)&prim.sspp_addr, | ||
3321 | af->sockaddr_len); | ||
3322 | if (err) | ||
3323 | return err; | ||
3324 | |||
3270 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ | 3325 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ |
3271 | chunk = sctp_make_asconf_set_prim(asoc, | 3326 | chunk = sctp_make_asconf_set_prim(asoc, |
3272 | (union sctp_addr *)&prim.sspp_addr); | 3327 | (union sctp_addr *)&prim.sspp_addr); |
@@ -5140,9 +5195,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) | |||
5140 | sctp_copy_sock(sock->sk, sk, asoc); | 5195 | sctp_copy_sock(sock->sk, sk, asoc); |
5141 | 5196 | ||
5142 | /* Make peeled-off sockets more like 1-1 accepted sockets. | 5197 | /* Make peeled-off sockets more like 1-1 accepted sockets. |
5143 | * Set the daddr and initialize id to something more random | 5198 | * Set the daddr and initialize id to something more random and also |
5199 | * copy over any ip options. | ||
5144 | */ | 5200 | */ |
5145 | sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); | 5201 | sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); |
5202 | sp->pf->copy_ip_options(sk, sock->sk); | ||
5146 | 5203 | ||
5147 | /* Populate the fields of the newsk from the oldsk and migrate the | 5204 | /* Populate the fields of the newsk from the oldsk and migrate the |
5148 | * asoc to the newsk. | 5205 | * asoc to the newsk. |
@@ -8465,6 +8522,8 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8465 | { | 8522 | { |
8466 | struct inet_sock *inet = inet_sk(sk); | 8523 | struct inet_sock *inet = inet_sk(sk); |
8467 | struct inet_sock *newinet; | 8524 | struct inet_sock *newinet; |
8525 | struct sctp_sock *sp = sctp_sk(sk); | ||
8526 | struct sctp_endpoint *ep = sp->ep; | ||
8468 | 8527 | ||
8469 | newsk->sk_type = sk->sk_type; | 8528 | newsk->sk_type = sk->sk_type; |
8470 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | 8529 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; |
@@ -8507,7 +8566,10 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8507 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) | 8566 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) |
8508 | net_enable_timestamp(); | 8567 | net_enable_timestamp(); |
8509 | 8568 | ||
8510 | security_sk_clone(sk, newsk); | 8569 | /* Set newsk security attributes from orginal sk and connection |
8570 | * security attribute from ep. | ||
8571 | */ | ||
8572 | security_sctp_sk_clone(ep, sk, newsk); | ||
8511 | } | 8573 | } |
8512 | 8574 | ||
8513 | static inline void sctp_copy_descendant(struct sock *sk_to, | 8575 | static inline void sctp_copy_descendant(struct sock *sk_to, |
diff --git a/security/security.c b/security/security.c index 02d734e69955..af53d2834e20 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -1473,6 +1473,7 @@ void security_inet_conn_established(struct sock *sk, | |||
1473 | { | 1473 | { |
1474 | call_void_hook(inet_conn_established, sk, skb); | 1474 | call_void_hook(inet_conn_established, sk, skb); |
1475 | } | 1475 | } |
1476 | EXPORT_SYMBOL(security_inet_conn_established); | ||
1476 | 1477 | ||
1477 | int security_secmark_relabel_packet(u32 secid) | 1478 | int security_secmark_relabel_packet(u32 secid) |
1478 | { | 1479 | { |
@@ -1528,6 +1529,27 @@ int security_tun_dev_open(void *security) | |||
1528 | } | 1529 | } |
1529 | EXPORT_SYMBOL(security_tun_dev_open); | 1530 | EXPORT_SYMBOL(security_tun_dev_open); |
1530 | 1531 | ||
1532 | int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb) | ||
1533 | { | ||
1534 | return call_int_hook(sctp_assoc_request, 0, ep, skb); | ||
1535 | } | ||
1536 | EXPORT_SYMBOL(security_sctp_assoc_request); | ||
1537 | |||
1538 | int security_sctp_bind_connect(struct sock *sk, int optname, | ||
1539 | struct sockaddr *address, int addrlen) | ||
1540 | { | ||
1541 | return call_int_hook(sctp_bind_connect, 0, sk, optname, | ||
1542 | address, addrlen); | ||
1543 | } | ||
1544 | EXPORT_SYMBOL(security_sctp_bind_connect); | ||
1545 | |||
1546 | void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, | ||
1547 | struct sock *newsk) | ||
1548 | { | ||
1549 | call_void_hook(sctp_sk_clone, ep, sk, newsk); | ||
1550 | } | ||
1551 | EXPORT_SYMBOL(security_sctp_sk_clone); | ||
1552 | |||
1531 | #endif /* CONFIG_SECURITY_NETWORK */ | 1553 | #endif /* CONFIG_SECURITY_NETWORK */ |
1532 | 1554 | ||
1533 | #ifdef CONFIG_SECURITY_INFINIBAND | 1555 | #ifdef CONFIG_SECURITY_INFINIBAND |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 2380b8d72cec..f3aedf077509 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -82,14 +82,42 @@ struct avc_callback_node { | |||
82 | struct avc_callback_node *next; | 82 | struct avc_callback_node *next; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* Exported via selinufs */ | ||
86 | unsigned int avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD; | ||
87 | |||
88 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 85 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
89 | DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 }; | 86 | DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 }; |
90 | #endif | 87 | #endif |
91 | 88 | ||
92 | static struct avc_cache avc_cache; | 89 | struct selinux_avc { |
90 | unsigned int avc_cache_threshold; | ||
91 | struct avc_cache avc_cache; | ||
92 | }; | ||
93 | |||
94 | static struct selinux_avc selinux_avc; | ||
95 | |||
96 | void selinux_avc_init(struct selinux_avc **avc) | ||
97 | { | ||
98 | int i; | ||
99 | |||
100 | selinux_avc.avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD; | ||
101 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | ||
102 | INIT_HLIST_HEAD(&selinux_avc.avc_cache.slots[i]); | ||
103 | spin_lock_init(&selinux_avc.avc_cache.slots_lock[i]); | ||
104 | } | ||
105 | atomic_set(&selinux_avc.avc_cache.active_nodes, 0); | ||
106 | atomic_set(&selinux_avc.avc_cache.lru_hint, 0); | ||
107 | *avc = &selinux_avc; | ||
108 | } | ||
109 | |||
110 | unsigned int avc_get_cache_threshold(struct selinux_avc *avc) | ||
111 | { | ||
112 | return avc->avc_cache_threshold; | ||
113 | } | ||
114 | |||
115 | void avc_set_cache_threshold(struct selinux_avc *avc, | ||
116 | unsigned int cache_threshold) | ||
117 | { | ||
118 | avc->avc_cache_threshold = cache_threshold; | ||
119 | } | ||
120 | |||
93 | static struct avc_callback_node *avc_callbacks; | 121 | static struct avc_callback_node *avc_callbacks; |
94 | static struct kmem_cache *avc_node_cachep; | 122 | static struct kmem_cache *avc_node_cachep; |
95 | static struct kmem_cache *avc_xperms_data_cachep; | 123 | static struct kmem_cache *avc_xperms_data_cachep; |
@@ -143,13 +171,14 @@ static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | |||
143 | * @tsid: target security identifier | 171 | * @tsid: target security identifier |
144 | * @tclass: target security class | 172 | * @tclass: target security class |
145 | */ | 173 | */ |
146 | static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass) | 174 | static void avc_dump_query(struct audit_buffer *ab, struct selinux_state *state, |
175 | u32 ssid, u32 tsid, u16 tclass) | ||
147 | { | 176 | { |
148 | int rc; | 177 | int rc; |
149 | char *scontext; | 178 | char *scontext; |
150 | u32 scontext_len; | 179 | u32 scontext_len; |
151 | 180 | ||
152 | rc = security_sid_to_context(ssid, &scontext, &scontext_len); | 181 | rc = security_sid_to_context(state, ssid, &scontext, &scontext_len); |
153 | if (rc) | 182 | if (rc) |
154 | audit_log_format(ab, "ssid=%d", ssid); | 183 | audit_log_format(ab, "ssid=%d", ssid); |
155 | else { | 184 | else { |
@@ -157,7 +186,7 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla | |||
157 | kfree(scontext); | 186 | kfree(scontext); |
158 | } | 187 | } |
159 | 188 | ||
160 | rc = security_sid_to_context(tsid, &scontext, &scontext_len); | 189 | rc = security_sid_to_context(state, tsid, &scontext, &scontext_len); |
161 | if (rc) | 190 | if (rc) |
162 | audit_log_format(ab, " tsid=%d", tsid); | 191 | audit_log_format(ab, " tsid=%d", tsid); |
163 | else { | 192 | else { |
@@ -176,15 +205,6 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla | |||
176 | */ | 205 | */ |
177 | void __init avc_init(void) | 206 | void __init avc_init(void) |
178 | { | 207 | { |
179 | int i; | ||
180 | |||
181 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | ||
182 | INIT_HLIST_HEAD(&avc_cache.slots[i]); | ||
183 | spin_lock_init(&avc_cache.slots_lock[i]); | ||
184 | } | ||
185 | atomic_set(&avc_cache.active_nodes, 0); | ||
186 | atomic_set(&avc_cache.lru_hint, 0); | ||
187 | |||
188 | avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), | 208 | avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), |
189 | 0, SLAB_PANIC, NULL); | 209 | 0, SLAB_PANIC, NULL); |
190 | avc_xperms_cachep = kmem_cache_create("avc_xperms_node", | 210 | avc_xperms_cachep = kmem_cache_create("avc_xperms_node", |
@@ -199,7 +219,7 @@ void __init avc_init(void) | |||
199 | 0, SLAB_PANIC, NULL); | 219 | 0, SLAB_PANIC, NULL); |
200 | } | 220 | } |
201 | 221 | ||
202 | int avc_get_hash_stats(char *page) | 222 | int avc_get_hash_stats(struct selinux_avc *avc, char *page) |
203 | { | 223 | { |
204 | int i, chain_len, max_chain_len, slots_used; | 224 | int i, chain_len, max_chain_len, slots_used; |
205 | struct avc_node *node; | 225 | struct avc_node *node; |
@@ -210,7 +230,7 @@ int avc_get_hash_stats(char *page) | |||
210 | slots_used = 0; | 230 | slots_used = 0; |
211 | max_chain_len = 0; | 231 | max_chain_len = 0; |
212 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | 232 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { |
213 | head = &avc_cache.slots[i]; | 233 | head = &avc->avc_cache.slots[i]; |
214 | if (!hlist_empty(head)) { | 234 | if (!hlist_empty(head)) { |
215 | slots_used++; | 235 | slots_used++; |
216 | chain_len = 0; | 236 | chain_len = 0; |
@@ -225,7 +245,7 @@ int avc_get_hash_stats(char *page) | |||
225 | 245 | ||
226 | return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n" | 246 | return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n" |
227 | "longest chain: %d\n", | 247 | "longest chain: %d\n", |
228 | atomic_read(&avc_cache.active_nodes), | 248 | atomic_read(&avc->avc_cache.active_nodes), |
229 | slots_used, AVC_CACHE_SLOTS, max_chain_len); | 249 | slots_used, AVC_CACHE_SLOTS, max_chain_len); |
230 | } | 250 | } |
231 | 251 | ||
@@ -462,11 +482,12 @@ static inline u32 avc_xperms_audit_required(u32 requested, | |||
462 | return audited; | 482 | return audited; |
463 | } | 483 | } |
464 | 484 | ||
465 | static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass, | 485 | static inline int avc_xperms_audit(struct selinux_state *state, |
466 | u32 requested, struct av_decision *avd, | 486 | u32 ssid, u32 tsid, u16 tclass, |
467 | struct extended_perms_decision *xpd, | 487 | u32 requested, struct av_decision *avd, |
468 | u8 perm, int result, | 488 | struct extended_perms_decision *xpd, |
469 | struct common_audit_data *ad) | 489 | u8 perm, int result, |
490 | struct common_audit_data *ad) | ||
470 | { | 491 | { |
471 | u32 audited, denied; | 492 | u32 audited, denied; |
472 | 493 | ||
@@ -474,7 +495,7 @@ static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass, | |||
474 | requested, avd, xpd, perm, result, &denied); | 495 | requested, avd, xpd, perm, result, &denied); |
475 | if (likely(!audited)) | 496 | if (likely(!audited)) |
476 | return 0; | 497 | return 0; |
477 | return slow_avc_audit(ssid, tsid, tclass, requested, | 498 | return slow_avc_audit(state, ssid, tsid, tclass, requested, |
478 | audited, denied, result, ad, 0); | 499 | audited, denied, result, ad, 0); |
479 | } | 500 | } |
480 | 501 | ||
@@ -486,29 +507,30 @@ static void avc_node_free(struct rcu_head *rhead) | |||
486 | avc_cache_stats_incr(frees); | 507 | avc_cache_stats_incr(frees); |
487 | } | 508 | } |
488 | 509 | ||
489 | static void avc_node_delete(struct avc_node *node) | 510 | static void avc_node_delete(struct selinux_avc *avc, struct avc_node *node) |
490 | { | 511 | { |
491 | hlist_del_rcu(&node->list); | 512 | hlist_del_rcu(&node->list); |
492 | call_rcu(&node->rhead, avc_node_free); | 513 | call_rcu(&node->rhead, avc_node_free); |
493 | atomic_dec(&avc_cache.active_nodes); | 514 | atomic_dec(&avc->avc_cache.active_nodes); |
494 | } | 515 | } |
495 | 516 | ||
496 | static void avc_node_kill(struct avc_node *node) | 517 | static void avc_node_kill(struct selinux_avc *avc, struct avc_node *node) |
497 | { | 518 | { |
498 | avc_xperms_free(node->ae.xp_node); | 519 | avc_xperms_free(node->ae.xp_node); |
499 | kmem_cache_free(avc_node_cachep, node); | 520 | kmem_cache_free(avc_node_cachep, node); |
500 | avc_cache_stats_incr(frees); | 521 | avc_cache_stats_incr(frees); |
501 | atomic_dec(&avc_cache.active_nodes); | 522 | atomic_dec(&avc->avc_cache.active_nodes); |
502 | } | 523 | } |
503 | 524 | ||
504 | static void avc_node_replace(struct avc_node *new, struct avc_node *old) | 525 | static void avc_node_replace(struct selinux_avc *avc, |
526 | struct avc_node *new, struct avc_node *old) | ||
505 | { | 527 | { |
506 | hlist_replace_rcu(&old->list, &new->list); | 528 | hlist_replace_rcu(&old->list, &new->list); |
507 | call_rcu(&old->rhead, avc_node_free); | 529 | call_rcu(&old->rhead, avc_node_free); |
508 | atomic_dec(&avc_cache.active_nodes); | 530 | atomic_dec(&avc->avc_cache.active_nodes); |
509 | } | 531 | } |
510 | 532 | ||
511 | static inline int avc_reclaim_node(void) | 533 | static inline int avc_reclaim_node(struct selinux_avc *avc) |
512 | { | 534 | { |
513 | struct avc_node *node; | 535 | struct avc_node *node; |
514 | int hvalue, try, ecx; | 536 | int hvalue, try, ecx; |
@@ -517,16 +539,17 @@ static inline int avc_reclaim_node(void) | |||
517 | spinlock_t *lock; | 539 | spinlock_t *lock; |
518 | 540 | ||
519 | for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) { | 541 | for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) { |
520 | hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1); | 542 | hvalue = atomic_inc_return(&avc->avc_cache.lru_hint) & |
521 | head = &avc_cache.slots[hvalue]; | 543 | (AVC_CACHE_SLOTS - 1); |
522 | lock = &avc_cache.slots_lock[hvalue]; | 544 | head = &avc->avc_cache.slots[hvalue]; |
545 | lock = &avc->avc_cache.slots_lock[hvalue]; | ||
523 | 546 | ||
524 | if (!spin_trylock_irqsave(lock, flags)) | 547 | if (!spin_trylock_irqsave(lock, flags)) |
525 | continue; | 548 | continue; |
526 | 549 | ||
527 | rcu_read_lock(); | 550 | rcu_read_lock(); |
528 | hlist_for_each_entry(node, head, list) { | 551 | hlist_for_each_entry(node, head, list) { |
529 | avc_node_delete(node); | 552 | avc_node_delete(avc, node); |
530 | avc_cache_stats_incr(reclaims); | 553 | avc_cache_stats_incr(reclaims); |
531 | ecx++; | 554 | ecx++; |
532 | if (ecx >= AVC_CACHE_RECLAIM) { | 555 | if (ecx >= AVC_CACHE_RECLAIM) { |
@@ -542,7 +565,7 @@ out: | |||
542 | return ecx; | 565 | return ecx; |
543 | } | 566 | } |
544 | 567 | ||
545 | static struct avc_node *avc_alloc_node(void) | 568 | static struct avc_node *avc_alloc_node(struct selinux_avc *avc) |
546 | { | 569 | { |
547 | struct avc_node *node; | 570 | struct avc_node *node; |
548 | 571 | ||
@@ -553,8 +576,9 @@ static struct avc_node *avc_alloc_node(void) | |||
553 | INIT_HLIST_NODE(&node->list); | 576 | INIT_HLIST_NODE(&node->list); |
554 | avc_cache_stats_incr(allocations); | 577 | avc_cache_stats_incr(allocations); |
555 | 578 | ||
556 | if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold) | 579 | if (atomic_inc_return(&avc->avc_cache.active_nodes) > |
557 | avc_reclaim_node(); | 580 | avc->avc_cache_threshold) |
581 | avc_reclaim_node(avc); | ||
558 | 582 | ||
559 | out: | 583 | out: |
560 | return node; | 584 | return node; |
@@ -568,14 +592,15 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl | |||
568 | memcpy(&node->ae.avd, avd, sizeof(node->ae.avd)); | 592 | memcpy(&node->ae.avd, avd, sizeof(node->ae.avd)); |
569 | } | 593 | } |
570 | 594 | ||
571 | static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | 595 | static inline struct avc_node *avc_search_node(struct selinux_avc *avc, |
596 | u32 ssid, u32 tsid, u16 tclass) | ||
572 | { | 597 | { |
573 | struct avc_node *node, *ret = NULL; | 598 | struct avc_node *node, *ret = NULL; |
574 | int hvalue; | 599 | int hvalue; |
575 | struct hlist_head *head; | 600 | struct hlist_head *head; |
576 | 601 | ||
577 | hvalue = avc_hash(ssid, tsid, tclass); | 602 | hvalue = avc_hash(ssid, tsid, tclass); |
578 | head = &avc_cache.slots[hvalue]; | 603 | head = &avc->avc_cache.slots[hvalue]; |
579 | hlist_for_each_entry_rcu(node, head, list) { | 604 | hlist_for_each_entry_rcu(node, head, list) { |
580 | if (ssid == node->ae.ssid && | 605 | if (ssid == node->ae.ssid && |
581 | tclass == node->ae.tclass && | 606 | tclass == node->ae.tclass && |
@@ -600,12 +625,13 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | |||
600 | * then this function returns the avc_node. | 625 | * then this function returns the avc_node. |
601 | * Otherwise, this function returns NULL. | 626 | * Otherwise, this function returns NULL. |
602 | */ | 627 | */ |
603 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) | 628 | static struct avc_node *avc_lookup(struct selinux_avc *avc, |
629 | u32 ssid, u32 tsid, u16 tclass) | ||
604 | { | 630 | { |
605 | struct avc_node *node; | 631 | struct avc_node *node; |
606 | 632 | ||
607 | avc_cache_stats_incr(lookups); | 633 | avc_cache_stats_incr(lookups); |
608 | node = avc_search_node(ssid, tsid, tclass); | 634 | node = avc_search_node(avc, ssid, tsid, tclass); |
609 | 635 | ||
610 | if (node) | 636 | if (node) |
611 | return node; | 637 | return node; |
@@ -614,7 +640,8 @@ static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) | |||
614 | return NULL; | 640 | return NULL; |
615 | } | 641 | } |
616 | 642 | ||
617 | static int avc_latest_notif_update(int seqno, int is_insert) | 643 | static int avc_latest_notif_update(struct selinux_avc *avc, |
644 | int seqno, int is_insert) | ||
618 | { | 645 | { |
619 | int ret = 0; | 646 | int ret = 0; |
620 | static DEFINE_SPINLOCK(notif_lock); | 647 | static DEFINE_SPINLOCK(notif_lock); |
@@ -622,14 +649,14 @@ static int avc_latest_notif_update(int seqno, int is_insert) | |||
622 | 649 | ||
623 | spin_lock_irqsave(¬if_lock, flag); | 650 | spin_lock_irqsave(¬if_lock, flag); |
624 | if (is_insert) { | 651 | if (is_insert) { |
625 | if (seqno < avc_cache.latest_notif) { | 652 | if (seqno < avc->avc_cache.latest_notif) { |
626 | printk(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n", | 653 | printk(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n", |
627 | seqno, avc_cache.latest_notif); | 654 | seqno, avc->avc_cache.latest_notif); |
628 | ret = -EAGAIN; | 655 | ret = -EAGAIN; |
629 | } | 656 | } |
630 | } else { | 657 | } else { |
631 | if (seqno > avc_cache.latest_notif) | 658 | if (seqno > avc->avc_cache.latest_notif) |
632 | avc_cache.latest_notif = seqno; | 659 | avc->avc_cache.latest_notif = seqno; |
633 | } | 660 | } |
634 | spin_unlock_irqrestore(¬if_lock, flag); | 661 | spin_unlock_irqrestore(¬if_lock, flag); |
635 | 662 | ||
@@ -654,18 +681,19 @@ static int avc_latest_notif_update(int seqno, int is_insert) | |||
654 | * the access vectors into a cache entry, returns | 681 | * the access vectors into a cache entry, returns |
655 | * avc_node inserted. Otherwise, this function returns NULL. | 682 | * avc_node inserted. Otherwise, this function returns NULL. |
656 | */ | 683 | */ |
657 | static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, | 684 | static struct avc_node *avc_insert(struct selinux_avc *avc, |
658 | struct av_decision *avd, | 685 | u32 ssid, u32 tsid, u16 tclass, |
659 | struct avc_xperms_node *xp_node) | 686 | struct av_decision *avd, |
687 | struct avc_xperms_node *xp_node) | ||
660 | { | 688 | { |
661 | struct avc_node *pos, *node = NULL; | 689 | struct avc_node *pos, *node = NULL; |
662 | int hvalue; | 690 | int hvalue; |
663 | unsigned long flag; | 691 | unsigned long flag; |
664 | 692 | ||
665 | if (avc_latest_notif_update(avd->seqno, 1)) | 693 | if (avc_latest_notif_update(avc, avd->seqno, 1)) |
666 | goto out; | 694 | goto out; |
667 | 695 | ||
668 | node = avc_alloc_node(); | 696 | node = avc_alloc_node(avc); |
669 | if (node) { | 697 | if (node) { |
670 | struct hlist_head *head; | 698 | struct hlist_head *head; |
671 | spinlock_t *lock; | 699 | spinlock_t *lock; |
@@ -678,15 +706,15 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, | |||
678 | kmem_cache_free(avc_node_cachep, node); | 706 | kmem_cache_free(avc_node_cachep, node); |
679 | return NULL; | 707 | return NULL; |
680 | } | 708 | } |
681 | head = &avc_cache.slots[hvalue]; | 709 | head = &avc->avc_cache.slots[hvalue]; |
682 | lock = &avc_cache.slots_lock[hvalue]; | 710 | lock = &avc->avc_cache.slots_lock[hvalue]; |
683 | 711 | ||
684 | spin_lock_irqsave(lock, flag); | 712 | spin_lock_irqsave(lock, flag); |
685 | hlist_for_each_entry(pos, head, list) { | 713 | hlist_for_each_entry(pos, head, list) { |
686 | if (pos->ae.ssid == ssid && | 714 | if (pos->ae.ssid == ssid && |
687 | pos->ae.tsid == tsid && | 715 | pos->ae.tsid == tsid && |
688 | pos->ae.tclass == tclass) { | 716 | pos->ae.tclass == tclass) { |
689 | avc_node_replace(node, pos); | 717 | avc_node_replace(avc, node, pos); |
690 | goto found; | 718 | goto found; |
691 | } | 719 | } |
692 | } | 720 | } |
@@ -724,9 +752,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | |||
724 | { | 752 | { |
725 | struct common_audit_data *ad = a; | 753 | struct common_audit_data *ad = a; |
726 | audit_log_format(ab, " "); | 754 | audit_log_format(ab, " "); |
727 | avc_dump_query(ab, ad->selinux_audit_data->ssid, | 755 | avc_dump_query(ab, ad->selinux_audit_data->state, |
728 | ad->selinux_audit_data->tsid, | 756 | ad->selinux_audit_data->ssid, |
729 | ad->selinux_audit_data->tclass); | 757 | ad->selinux_audit_data->tsid, |
758 | ad->selinux_audit_data->tclass); | ||
730 | if (ad->selinux_audit_data->denied) { | 759 | if (ad->selinux_audit_data->denied) { |
731 | audit_log_format(ab, " permissive=%u", | 760 | audit_log_format(ab, " permissive=%u", |
732 | ad->selinux_audit_data->result ? 0 : 1); | 761 | ad->selinux_audit_data->result ? 0 : 1); |
@@ -734,10 +763,11 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | |||
734 | } | 763 | } |
735 | 764 | ||
736 | /* This is the slow part of avc audit with big stack footprint */ | 765 | /* This is the slow part of avc audit with big stack footprint */ |
737 | noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | 766 | noinline int slow_avc_audit(struct selinux_state *state, |
738 | u32 requested, u32 audited, u32 denied, int result, | 767 | u32 ssid, u32 tsid, u16 tclass, |
739 | struct common_audit_data *a, | 768 | u32 requested, u32 audited, u32 denied, int result, |
740 | unsigned flags) | 769 | struct common_audit_data *a, |
770 | unsigned int flags) | ||
741 | { | 771 | { |
742 | struct common_audit_data stack_data; | 772 | struct common_audit_data stack_data; |
743 | struct selinux_audit_data sad; | 773 | struct selinux_audit_data sad; |
@@ -765,6 +795,7 @@ noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | |||
765 | sad.audited = audited; | 795 | sad.audited = audited; |
766 | sad.denied = denied; | 796 | sad.denied = denied; |
767 | sad.result = result; | 797 | sad.result = result; |
798 | sad.state = state; | ||
768 | 799 | ||
769 | a->selinux_audit_data = &sad; | 800 | a->selinux_audit_data = &sad; |
770 | 801 | ||
@@ -813,10 +844,11 @@ out: | |||
813 | * otherwise, this function updates the AVC entry. The original AVC-entry object | 844 | * otherwise, this function updates the AVC entry. The original AVC-entry object |
814 | * will release later by RCU. | 845 | * will release later by RCU. |
815 | */ | 846 | */ |
816 | static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, | 847 | static int avc_update_node(struct selinux_avc *avc, |
817 | u32 tsid, u16 tclass, u32 seqno, | 848 | u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, |
818 | struct extended_perms_decision *xpd, | 849 | u32 tsid, u16 tclass, u32 seqno, |
819 | u32 flags) | 850 | struct extended_perms_decision *xpd, |
851 | u32 flags) | ||
820 | { | 852 | { |
821 | int hvalue, rc = 0; | 853 | int hvalue, rc = 0; |
822 | unsigned long flag; | 854 | unsigned long flag; |
@@ -824,7 +856,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, | |||
824 | struct hlist_head *head; | 856 | struct hlist_head *head; |
825 | spinlock_t *lock; | 857 | spinlock_t *lock; |
826 | 858 | ||
827 | node = avc_alloc_node(); | 859 | node = avc_alloc_node(avc); |
828 | if (!node) { | 860 | if (!node) { |
829 | rc = -ENOMEM; | 861 | rc = -ENOMEM; |
830 | goto out; | 862 | goto out; |
@@ -833,8 +865,8 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, | |||
833 | /* Lock the target slot */ | 865 | /* Lock the target slot */ |
834 | hvalue = avc_hash(ssid, tsid, tclass); | 866 | hvalue = avc_hash(ssid, tsid, tclass); |
835 | 867 | ||
836 | head = &avc_cache.slots[hvalue]; | 868 | head = &avc->avc_cache.slots[hvalue]; |
837 | lock = &avc_cache.slots_lock[hvalue]; | 869 | lock = &avc->avc_cache.slots_lock[hvalue]; |
838 | 870 | ||
839 | spin_lock_irqsave(lock, flag); | 871 | spin_lock_irqsave(lock, flag); |
840 | 872 | ||
@@ -850,7 +882,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, | |||
850 | 882 | ||
851 | if (!orig) { | 883 | if (!orig) { |
852 | rc = -ENOENT; | 884 | rc = -ENOENT; |
853 | avc_node_kill(node); | 885 | avc_node_kill(avc, node); |
854 | goto out_unlock; | 886 | goto out_unlock; |
855 | } | 887 | } |
856 | 888 | ||
@@ -894,7 +926,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, | |||
894 | avc_add_xperms_decision(node, xpd); | 926 | avc_add_xperms_decision(node, xpd); |
895 | break; | 927 | break; |
896 | } | 928 | } |
897 | avc_node_replace(node, orig); | 929 | avc_node_replace(avc, node, orig); |
898 | out_unlock: | 930 | out_unlock: |
899 | spin_unlock_irqrestore(lock, flag); | 931 | spin_unlock_irqrestore(lock, flag); |
900 | out: | 932 | out: |
@@ -904,7 +936,7 @@ out: | |||
904 | /** | 936 | /** |
905 | * avc_flush - Flush the cache | 937 | * avc_flush - Flush the cache |
906 | */ | 938 | */ |
907 | static void avc_flush(void) | 939 | static void avc_flush(struct selinux_avc *avc) |
908 | { | 940 | { |
909 | struct hlist_head *head; | 941 | struct hlist_head *head; |
910 | struct avc_node *node; | 942 | struct avc_node *node; |
@@ -913,8 +945,8 @@ static void avc_flush(void) | |||
913 | int i; | 945 | int i; |
914 | 946 | ||
915 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | 947 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { |
916 | head = &avc_cache.slots[i]; | 948 | head = &avc->avc_cache.slots[i]; |
917 | lock = &avc_cache.slots_lock[i]; | 949 | lock = &avc->avc_cache.slots_lock[i]; |
918 | 950 | ||
919 | spin_lock_irqsave(lock, flag); | 951 | spin_lock_irqsave(lock, flag); |
920 | /* | 952 | /* |
@@ -923,7 +955,7 @@ static void avc_flush(void) | |||
923 | */ | 955 | */ |
924 | rcu_read_lock(); | 956 | rcu_read_lock(); |
925 | hlist_for_each_entry(node, head, list) | 957 | hlist_for_each_entry(node, head, list) |
926 | avc_node_delete(node); | 958 | avc_node_delete(avc, node); |
927 | rcu_read_unlock(); | 959 | rcu_read_unlock(); |
928 | spin_unlock_irqrestore(lock, flag); | 960 | spin_unlock_irqrestore(lock, flag); |
929 | } | 961 | } |
@@ -933,12 +965,12 @@ static void avc_flush(void) | |||
933 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. | 965 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. |
934 | * @seqno: policy sequence number | 966 | * @seqno: policy sequence number |
935 | */ | 967 | */ |
936 | int avc_ss_reset(u32 seqno) | 968 | int avc_ss_reset(struct selinux_avc *avc, u32 seqno) |
937 | { | 969 | { |
938 | struct avc_callback_node *c; | 970 | struct avc_callback_node *c; |
939 | int rc = 0, tmprc; | 971 | int rc = 0, tmprc; |
940 | 972 | ||
941 | avc_flush(); | 973 | avc_flush(avc); |
942 | 974 | ||
943 | for (c = avc_callbacks; c; c = c->next) { | 975 | for (c = avc_callbacks; c; c = c->next) { |
944 | if (c->events & AVC_CALLBACK_RESET) { | 976 | if (c->events & AVC_CALLBACK_RESET) { |
@@ -950,7 +982,7 @@ int avc_ss_reset(u32 seqno) | |||
950 | } | 982 | } |
951 | } | 983 | } |
952 | 984 | ||
953 | avc_latest_notif_update(seqno, 0); | 985 | avc_latest_notif_update(avc, seqno, 0); |
954 | return rc; | 986 | return rc; |
955 | } | 987 | } |
956 | 988 | ||
@@ -963,30 +995,34 @@ int avc_ss_reset(u32 seqno) | |||
963 | * Don't inline this, since it's the slow-path and just | 995 | * Don't inline this, since it's the slow-path and just |
964 | * results in a bigger stack frame. | 996 | * results in a bigger stack frame. |
965 | */ | 997 | */ |
966 | static noinline struct avc_node *avc_compute_av(u32 ssid, u32 tsid, | 998 | static noinline |
967 | u16 tclass, struct av_decision *avd, | 999 | struct avc_node *avc_compute_av(struct selinux_state *state, |
968 | struct avc_xperms_node *xp_node) | 1000 | u32 ssid, u32 tsid, |
1001 | u16 tclass, struct av_decision *avd, | ||
1002 | struct avc_xperms_node *xp_node) | ||
969 | { | 1003 | { |
970 | rcu_read_unlock(); | 1004 | rcu_read_unlock(); |
971 | INIT_LIST_HEAD(&xp_node->xpd_head); | 1005 | INIT_LIST_HEAD(&xp_node->xpd_head); |
972 | security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp); | 1006 | security_compute_av(state, ssid, tsid, tclass, avd, &xp_node->xp); |
973 | rcu_read_lock(); | 1007 | rcu_read_lock(); |
974 | return avc_insert(ssid, tsid, tclass, avd, xp_node); | 1008 | return avc_insert(state->avc, ssid, tsid, tclass, avd, xp_node); |
975 | } | 1009 | } |
976 | 1010 | ||
977 | static noinline int avc_denied(u32 ssid, u32 tsid, | 1011 | static noinline int avc_denied(struct selinux_state *state, |
978 | u16 tclass, u32 requested, | 1012 | u32 ssid, u32 tsid, |
979 | u8 driver, u8 xperm, unsigned flags, | 1013 | u16 tclass, u32 requested, |
980 | struct av_decision *avd) | 1014 | u8 driver, u8 xperm, unsigned int flags, |
1015 | struct av_decision *avd) | ||
981 | { | 1016 | { |
982 | if (flags & AVC_STRICT) | 1017 | if (flags & AVC_STRICT) |
983 | return -EACCES; | 1018 | return -EACCES; |
984 | 1019 | ||
985 | if (selinux_enforcing && !(avd->flags & AVD_FLAGS_PERMISSIVE)) | 1020 | if (enforcing_enabled(state) && |
1021 | !(avd->flags & AVD_FLAGS_PERMISSIVE)) | ||
986 | return -EACCES; | 1022 | return -EACCES; |
987 | 1023 | ||
988 | avc_update_node(AVC_CALLBACK_GRANT, requested, driver, xperm, ssid, | 1024 | avc_update_node(state->avc, AVC_CALLBACK_GRANT, requested, driver, |
989 | tsid, tclass, avd->seqno, NULL, flags); | 1025 | xperm, ssid, tsid, tclass, avd->seqno, NULL, flags); |
990 | return 0; | 1026 | return 0; |
991 | } | 1027 | } |
992 | 1028 | ||
@@ -997,8 +1033,9 @@ static noinline int avc_denied(u32 ssid, u32 tsid, | |||
997 | * as-is the case with ioctls, then multiple may be chained together and the | 1033 | * as-is the case with ioctls, then multiple may be chained together and the |
998 | * driver field is used to specify which set contains the permission. | 1034 | * driver field is used to specify which set contains the permission. |
999 | */ | 1035 | */ |
1000 | int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, | 1036 | int avc_has_extended_perms(struct selinux_state *state, |
1001 | u8 driver, u8 xperm, struct common_audit_data *ad) | 1037 | u32 ssid, u32 tsid, u16 tclass, u32 requested, |
1038 | u8 driver, u8 xperm, struct common_audit_data *ad) | ||
1002 | { | 1039 | { |
1003 | struct avc_node *node; | 1040 | struct avc_node *node; |
1004 | struct av_decision avd; | 1041 | struct av_decision avd; |
@@ -1017,9 +1054,9 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, | |||
1017 | 1054 | ||
1018 | rcu_read_lock(); | 1055 | rcu_read_lock(); |
1019 | 1056 | ||
1020 | node = avc_lookup(ssid, tsid, tclass); | 1057 | node = avc_lookup(state->avc, ssid, tsid, tclass); |
1021 | if (unlikely(!node)) { | 1058 | if (unlikely(!node)) { |
1022 | node = avc_compute_av(ssid, tsid, tclass, &avd, xp_node); | 1059 | node = avc_compute_av(state, ssid, tsid, tclass, &avd, xp_node); |
1023 | } else { | 1060 | } else { |
1024 | memcpy(&avd, &node->ae.avd, sizeof(avd)); | 1061 | memcpy(&avd, &node->ae.avd, sizeof(avd)); |
1025 | xp_node = node->ae.xp_node; | 1062 | xp_node = node->ae.xp_node; |
@@ -1043,11 +1080,12 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, | |||
1043 | goto decision; | 1080 | goto decision; |
1044 | } | 1081 | } |
1045 | rcu_read_unlock(); | 1082 | rcu_read_unlock(); |
1046 | security_compute_xperms_decision(ssid, tsid, tclass, driver, | 1083 | security_compute_xperms_decision(state, ssid, tsid, tclass, |
1047 | &local_xpd); | 1084 | driver, &local_xpd); |
1048 | rcu_read_lock(); | 1085 | rcu_read_lock(); |
1049 | avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver, xperm, | 1086 | avc_update_node(state->avc, AVC_CALLBACK_ADD_XPERMS, requested, |
1050 | ssid, tsid, tclass, avd.seqno, &local_xpd, 0); | 1087 | driver, xperm, ssid, tsid, tclass, avd.seqno, |
1088 | &local_xpd, 0); | ||
1051 | } else { | 1089 | } else { |
1052 | avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd); | 1090 | avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd); |
1053 | } | 1091 | } |
@@ -1059,12 +1097,12 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, | |||
1059 | decision: | 1097 | decision: |
1060 | denied = requested & ~(avd.allowed); | 1098 | denied = requested & ~(avd.allowed); |
1061 | if (unlikely(denied)) | 1099 | if (unlikely(denied)) |
1062 | rc = avc_denied(ssid, tsid, tclass, requested, driver, xperm, | 1100 | rc = avc_denied(state, ssid, tsid, tclass, requested, |
1063 | AVC_EXTENDED_PERMS, &avd); | 1101 | driver, xperm, AVC_EXTENDED_PERMS, &avd); |
1064 | 1102 | ||
1065 | rcu_read_unlock(); | 1103 | rcu_read_unlock(); |
1066 | 1104 | ||
1067 | rc2 = avc_xperms_audit(ssid, tsid, tclass, requested, | 1105 | rc2 = avc_xperms_audit(state, ssid, tsid, tclass, requested, |
1068 | &avd, xpd, xperm, rc, ad); | 1106 | &avd, xpd, xperm, rc, ad); |
1069 | if (rc2) | 1107 | if (rc2) |
1070 | return rc2; | 1108 | return rc2; |
@@ -1091,10 +1129,11 @@ decision: | |||
1091 | * auditing, e.g. in cases where a lock must be held for the check but | 1129 | * auditing, e.g. in cases where a lock must be held for the check but |
1092 | * should be released for the auditing. | 1130 | * should be released for the auditing. |
1093 | */ | 1131 | */ |
1094 | inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 1132 | inline int avc_has_perm_noaudit(struct selinux_state *state, |
1095 | u16 tclass, u32 requested, | 1133 | u32 ssid, u32 tsid, |
1096 | unsigned flags, | 1134 | u16 tclass, u32 requested, |
1097 | struct av_decision *avd) | 1135 | unsigned int flags, |
1136 | struct av_decision *avd) | ||
1098 | { | 1137 | { |
1099 | struct avc_node *node; | 1138 | struct avc_node *node; |
1100 | struct avc_xperms_node xp_node; | 1139 | struct avc_xperms_node xp_node; |
@@ -1105,15 +1144,16 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
1105 | 1144 | ||
1106 | rcu_read_lock(); | 1145 | rcu_read_lock(); |
1107 | 1146 | ||
1108 | node = avc_lookup(ssid, tsid, tclass); | 1147 | node = avc_lookup(state->avc, ssid, tsid, tclass); |
1109 | if (unlikely(!node)) | 1148 | if (unlikely(!node)) |
1110 | node = avc_compute_av(ssid, tsid, tclass, avd, &xp_node); | 1149 | node = avc_compute_av(state, ssid, tsid, tclass, avd, &xp_node); |
1111 | else | 1150 | else |
1112 | memcpy(avd, &node->ae.avd, sizeof(*avd)); | 1151 | memcpy(avd, &node->ae.avd, sizeof(*avd)); |
1113 | 1152 | ||
1114 | denied = requested & ~(avd->allowed); | 1153 | denied = requested & ~(avd->allowed); |
1115 | if (unlikely(denied)) | 1154 | if (unlikely(denied)) |
1116 | rc = avc_denied(ssid, tsid, tclass, requested, 0, 0, flags, avd); | 1155 | rc = avc_denied(state, ssid, tsid, tclass, requested, 0, 0, |
1156 | flags, avd); | ||
1117 | 1157 | ||
1118 | rcu_read_unlock(); | 1158 | rcu_read_unlock(); |
1119 | return rc; | 1159 | return rc; |
@@ -1135,39 +1175,43 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
1135 | * permissions are granted, -%EACCES if any permissions are denied, or | 1175 | * permissions are granted, -%EACCES if any permissions are denied, or |
1136 | * another -errno upon other errors. | 1176 | * another -errno upon other errors. |
1137 | */ | 1177 | */ |
1138 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 1178 | int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, |
1139 | u32 requested, struct common_audit_data *auditdata) | 1179 | u32 requested, struct common_audit_data *auditdata) |
1140 | { | 1180 | { |
1141 | struct av_decision avd; | 1181 | struct av_decision avd; |
1142 | int rc, rc2; | 1182 | int rc, rc2; |
1143 | 1183 | ||
1144 | rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); | 1184 | rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0, |
1185 | &avd); | ||
1145 | 1186 | ||
1146 | rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, 0); | 1187 | rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, |
1188 | auditdata, 0); | ||
1147 | if (rc2) | 1189 | if (rc2) |
1148 | return rc2; | 1190 | return rc2; |
1149 | return rc; | 1191 | return rc; |
1150 | } | 1192 | } |
1151 | 1193 | ||
1152 | int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, | 1194 | int avc_has_perm_flags(struct selinux_state *state, |
1153 | u32 requested, struct common_audit_data *auditdata, | 1195 | u32 ssid, u32 tsid, u16 tclass, u32 requested, |
1196 | struct common_audit_data *auditdata, | ||
1154 | int flags) | 1197 | int flags) |
1155 | { | 1198 | { |
1156 | struct av_decision avd; | 1199 | struct av_decision avd; |
1157 | int rc, rc2; | 1200 | int rc, rc2; |
1158 | 1201 | ||
1159 | rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); | 1202 | rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0, |
1203 | &avd); | ||
1160 | 1204 | ||
1161 | rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, | 1205 | rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, |
1162 | auditdata, flags); | 1206 | auditdata, flags); |
1163 | if (rc2) | 1207 | if (rc2) |
1164 | return rc2; | 1208 | return rc2; |
1165 | return rc; | 1209 | return rc; |
1166 | } | 1210 | } |
1167 | 1211 | ||
1168 | u32 avc_policy_seqno(void) | 1212 | u32 avc_policy_seqno(struct selinux_state *state) |
1169 | { | 1213 | { |
1170 | return avc_cache.latest_notif; | 1214 | return state->avc->avc_cache.latest_notif; |
1171 | } | 1215 | } |
1172 | 1216 | ||
1173 | void avc_disable(void) | 1217 | void avc_disable(void) |
@@ -1184,7 +1228,7 @@ void avc_disable(void) | |||
1184 | * the cache and get that memory back. | 1228 | * the cache and get that memory back. |
1185 | */ | 1229 | */ |
1186 | if (avc_node_cachep) { | 1230 | if (avc_node_cachep) { |
1187 | avc_flush(); | 1231 | avc_flush(selinux_state.avc); |
1188 | /* kmem_cache_destroy(avc_node_cachep); */ | 1232 | /* kmem_cache_destroy(avc_node_cachep); */ |
1189 | } | 1233 | } |
1190 | } | 1234 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 925e546b5a87..0314fc766134 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -67,6 +67,8 @@ | |||
67 | #include <linux/tcp.h> | 67 | #include <linux/tcp.h> |
68 | #include <linux/udp.h> | 68 | #include <linux/udp.h> |
69 | #include <linux/dccp.h> | 69 | #include <linux/dccp.h> |
70 | #include <linux/sctp.h> | ||
71 | #include <net/sctp/structs.h> | ||
70 | #include <linux/quota.h> | 72 | #include <linux/quota.h> |
71 | #include <linux/un.h> /* for Unix socket types */ | 73 | #include <linux/un.h> /* for Unix socket types */ |
72 | #include <net/af_unix.h> /* for Unix socket types */ | 74 | #include <net/af_unix.h> /* for Unix socket types */ |
@@ -98,20 +100,24 @@ | |||
98 | #include "audit.h" | 100 | #include "audit.h" |
99 | #include "avc_ss.h" | 101 | #include "avc_ss.h" |
100 | 102 | ||
103 | struct selinux_state selinux_state; | ||
104 | |||
101 | /* SECMARK reference count */ | 105 | /* SECMARK reference count */ |
102 | static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); | 106 | static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); |
103 | 107 | ||
104 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | 108 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP |
105 | int selinux_enforcing; | 109 | static int selinux_enforcing_boot; |
106 | 110 | ||
107 | static int __init enforcing_setup(char *str) | 111 | static int __init enforcing_setup(char *str) |
108 | { | 112 | { |
109 | unsigned long enforcing; | 113 | unsigned long enforcing; |
110 | if (!kstrtoul(str, 0, &enforcing)) | 114 | if (!kstrtoul(str, 0, &enforcing)) |
111 | selinux_enforcing = enforcing ? 1 : 0; | 115 | selinux_enforcing_boot = enforcing ? 1 : 0; |
112 | return 1; | 116 | return 1; |
113 | } | 117 | } |
114 | __setup("enforcing=", enforcing_setup); | 118 | __setup("enforcing=", enforcing_setup); |
119 | #else | ||
120 | #define selinux_enforcing_boot 1 | ||
115 | #endif | 121 | #endif |
116 | 122 | ||
117 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | 123 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM |
@@ -129,6 +135,19 @@ __setup("selinux=", selinux_enabled_setup); | |||
129 | int selinux_enabled = 1; | 135 | int selinux_enabled = 1; |
130 | #endif | 136 | #endif |
131 | 137 | ||
138 | static unsigned int selinux_checkreqprot_boot = | ||
139 | CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; | ||
140 | |||
141 | static int __init checkreqprot_setup(char *str) | ||
142 | { | ||
143 | unsigned long checkreqprot; | ||
144 | |||
145 | if (!kstrtoul(str, 0, &checkreqprot)) | ||
146 | selinux_checkreqprot_boot = checkreqprot ? 1 : 0; | ||
147 | return 1; | ||
148 | } | ||
149 | __setup("checkreqprot=", checkreqprot_setup); | ||
150 | |||
132 | static struct kmem_cache *sel_inode_cache; | 151 | static struct kmem_cache *sel_inode_cache; |
133 | static struct kmem_cache *file_security_cache; | 152 | static struct kmem_cache *file_security_cache; |
134 | 153 | ||
@@ -145,7 +164,8 @@ static struct kmem_cache *file_security_cache; | |||
145 | */ | 164 | */ |
146 | static int selinux_secmark_enabled(void) | 165 | static int selinux_secmark_enabled(void) |
147 | { | 166 | { |
148 | return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount)); | 167 | return (selinux_policycap_alwaysnetwork() || |
168 | atomic_read(&selinux_secmark_refcount)); | ||
149 | } | 169 | } |
150 | 170 | ||
151 | /** | 171 | /** |
@@ -160,7 +180,8 @@ static int selinux_secmark_enabled(void) | |||
160 | */ | 180 | */ |
161 | static int selinux_peerlbl_enabled(void) | 181 | static int selinux_peerlbl_enabled(void) |
162 | { | 182 | { |
163 | return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled()); | 183 | return (selinux_policycap_alwaysnetwork() || |
184 | netlbl_enabled() || selinux_xfrm_enabled()); | ||
164 | } | 185 | } |
165 | 186 | ||
166 | static int selinux_netcache_avc_callback(u32 event) | 187 | static int selinux_netcache_avc_callback(u32 event) |
@@ -264,7 +285,8 @@ static int __inode_security_revalidate(struct inode *inode, | |||
264 | 285 | ||
265 | might_sleep_if(may_sleep); | 286 | might_sleep_if(may_sleep); |
266 | 287 | ||
267 | if (ss_initialized && isec->initialized != LABEL_INITIALIZED) { | 288 | if (selinux_state.initialized && |
289 | isec->initialized != LABEL_INITIALIZED) { | ||
268 | if (!may_sleep) | 290 | if (!may_sleep) |
269 | return -ECHILD; | 291 | return -ECHILD; |
270 | 292 | ||
@@ -446,12 +468,14 @@ static int may_context_mount_sb_relabel(u32 sid, | |||
446 | const struct task_security_struct *tsec = cred->security; | 468 | const struct task_security_struct *tsec = cred->security; |
447 | int rc; | 469 | int rc; |
448 | 470 | ||
449 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 471 | rc = avc_has_perm(&selinux_state, |
472 | tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | ||
450 | FILESYSTEM__RELABELFROM, NULL); | 473 | FILESYSTEM__RELABELFROM, NULL); |
451 | if (rc) | 474 | if (rc) |
452 | return rc; | 475 | return rc; |
453 | 476 | ||
454 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, | 477 | rc = avc_has_perm(&selinux_state, |
478 | tsec->sid, sid, SECCLASS_FILESYSTEM, | ||
455 | FILESYSTEM__RELABELTO, NULL); | 479 | FILESYSTEM__RELABELTO, NULL); |
456 | return rc; | 480 | return rc; |
457 | } | 481 | } |
@@ -462,12 +486,14 @@ static int may_context_mount_inode_relabel(u32 sid, | |||
462 | { | 486 | { |
463 | const struct task_security_struct *tsec = cred->security; | 487 | const struct task_security_struct *tsec = cred->security; |
464 | int rc; | 488 | int rc; |
465 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 489 | rc = avc_has_perm(&selinux_state, |
490 | tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | ||
466 | FILESYSTEM__RELABELFROM, NULL); | 491 | FILESYSTEM__RELABELFROM, NULL); |
467 | if (rc) | 492 | if (rc) |
468 | return rc; | 493 | return rc; |
469 | 494 | ||
470 | rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, | 495 | rc = avc_has_perm(&selinux_state, |
496 | sid, sbsec->sid, SECCLASS_FILESYSTEM, | ||
471 | FILESYSTEM__ASSOCIATE, NULL); | 497 | FILESYSTEM__ASSOCIATE, NULL); |
472 | return rc; | 498 | return rc; |
473 | } | 499 | } |
@@ -486,7 +512,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) | |||
486 | !strcmp(sb->s_type->name, "debugfs") || | 512 | !strcmp(sb->s_type->name, "debugfs") || |
487 | !strcmp(sb->s_type->name, "tracefs") || | 513 | !strcmp(sb->s_type->name, "tracefs") || |
488 | !strcmp(sb->s_type->name, "rootfs") || | 514 | !strcmp(sb->s_type->name, "rootfs") || |
489 | (selinux_policycap_cgroupseclabel && | 515 | (selinux_policycap_cgroupseclabel() && |
490 | (!strcmp(sb->s_type->name, "cgroup") || | 516 | (!strcmp(sb->s_type->name, "cgroup") || |
491 | !strcmp(sb->s_type->name, "cgroup2"))); | 517 | !strcmp(sb->s_type->name, "cgroup2"))); |
492 | } | 518 | } |
@@ -586,7 +612,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
586 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 612 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
587 | return -EINVAL; | 613 | return -EINVAL; |
588 | 614 | ||
589 | if (!ss_initialized) | 615 | if (!selinux_state.initialized) |
590 | return -EINVAL; | 616 | return -EINVAL; |
591 | 617 | ||
592 | /* make sure we always check enough bits to cover the mask */ | 618 | /* make sure we always check enough bits to cover the mask */ |
@@ -617,21 +643,25 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
617 | 643 | ||
618 | i = 0; | 644 | i = 0; |
619 | if (sbsec->flags & FSCONTEXT_MNT) { | 645 | if (sbsec->flags & FSCONTEXT_MNT) { |
620 | rc = security_sid_to_context(sbsec->sid, &context, &len); | 646 | rc = security_sid_to_context(&selinux_state, sbsec->sid, |
647 | &context, &len); | ||
621 | if (rc) | 648 | if (rc) |
622 | goto out_free; | 649 | goto out_free; |
623 | opts->mnt_opts[i] = context; | 650 | opts->mnt_opts[i] = context; |
624 | opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; | 651 | opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; |
625 | } | 652 | } |
626 | if (sbsec->flags & CONTEXT_MNT) { | 653 | if (sbsec->flags & CONTEXT_MNT) { |
627 | rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); | 654 | rc = security_sid_to_context(&selinux_state, |
655 | sbsec->mntpoint_sid, | ||
656 | &context, &len); | ||
628 | if (rc) | 657 | if (rc) |
629 | goto out_free; | 658 | goto out_free; |
630 | opts->mnt_opts[i] = context; | 659 | opts->mnt_opts[i] = context; |
631 | opts->mnt_opts_flags[i++] = CONTEXT_MNT; | 660 | opts->mnt_opts_flags[i++] = CONTEXT_MNT; |
632 | } | 661 | } |
633 | if (sbsec->flags & DEFCONTEXT_MNT) { | 662 | if (sbsec->flags & DEFCONTEXT_MNT) { |
634 | rc = security_sid_to_context(sbsec->def_sid, &context, &len); | 663 | rc = security_sid_to_context(&selinux_state, sbsec->def_sid, |
664 | &context, &len); | ||
635 | if (rc) | 665 | if (rc) |
636 | goto out_free; | 666 | goto out_free; |
637 | opts->mnt_opts[i] = context; | 667 | opts->mnt_opts[i] = context; |
@@ -641,7 +671,8 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
641 | struct dentry *root = sbsec->sb->s_root; | 671 | struct dentry *root = sbsec->sb->s_root; |
642 | struct inode_security_struct *isec = backing_inode_security(root); | 672 | struct inode_security_struct *isec = backing_inode_security(root); |
643 | 673 | ||
644 | rc = security_sid_to_context(isec->sid, &context, &len); | 674 | rc = security_sid_to_context(&selinux_state, isec->sid, |
675 | &context, &len); | ||
645 | if (rc) | 676 | if (rc) |
646 | goto out_free; | 677 | goto out_free; |
647 | opts->mnt_opts[i] = context; | 678 | opts->mnt_opts[i] = context; |
@@ -704,7 +735,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
704 | 735 | ||
705 | mutex_lock(&sbsec->lock); | 736 | mutex_lock(&sbsec->lock); |
706 | 737 | ||
707 | if (!ss_initialized) { | 738 | if (!selinux_state.initialized) { |
708 | if (!num_opts) { | 739 | if (!num_opts) { |
709 | /* Defer initialization until selinux_complete_init, | 740 | /* Defer initialization until selinux_complete_init, |
710 | after the initial policy is loaded and the security | 741 | after the initial policy is loaded and the security |
@@ -750,7 +781,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
750 | 781 | ||
751 | if (flags[i] == SBLABEL_MNT) | 782 | if (flags[i] == SBLABEL_MNT) |
752 | continue; | 783 | continue; |
753 | rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL); | 784 | rc = security_context_str_to_sid(&selinux_state, |
785 | mount_options[i], &sid, | ||
786 | GFP_KERNEL); | ||
754 | if (rc) { | 787 | if (rc) { |
755 | printk(KERN_WARNING "SELinux: security_context_str_to_sid" | 788 | printk(KERN_WARNING "SELinux: security_context_str_to_sid" |
756 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 789 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -826,7 +859,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
826 | * Determine the labeling behavior to use for this | 859 | * Determine the labeling behavior to use for this |
827 | * filesystem type. | 860 | * filesystem type. |
828 | */ | 861 | */ |
829 | rc = security_fs_use(sb); | 862 | rc = security_fs_use(&selinux_state, sb); |
830 | if (rc) { | 863 | if (rc) { |
831 | printk(KERN_WARNING | 864 | printk(KERN_WARNING |
832 | "%s: security_fs_use(%s) returned %d\n", | 865 | "%s: security_fs_use(%s) returned %d\n", |
@@ -851,7 +884,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
851 | } | 884 | } |
852 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { | 885 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { |
853 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; | 886 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; |
854 | rc = security_transition_sid(current_sid(), current_sid(), | 887 | rc = security_transition_sid(&selinux_state, |
888 | current_sid(), | ||
889 | current_sid(), | ||
855 | SECCLASS_FILE, NULL, | 890 | SECCLASS_FILE, NULL, |
856 | &sbsec->mntpoint_sid); | 891 | &sbsec->mntpoint_sid); |
857 | if (rc) | 892 | if (rc) |
@@ -987,7 +1022,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
987 | * if the parent was able to be mounted it clearly had no special lsm | 1022 | * if the parent was able to be mounted it clearly had no special lsm |
988 | * mount options. thus we can safely deal with this superblock later | 1023 | * mount options. thus we can safely deal with this superblock later |
989 | */ | 1024 | */ |
990 | if (!ss_initialized) | 1025 | if (!selinux_state.initialized) |
991 | return 0; | 1026 | return 0; |
992 | 1027 | ||
993 | /* | 1028 | /* |
@@ -1014,7 +1049,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
1014 | 1049 | ||
1015 | if (newsbsec->behavior == SECURITY_FS_USE_NATIVE && | 1050 | if (newsbsec->behavior == SECURITY_FS_USE_NATIVE && |
1016 | !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) { | 1051 | !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) { |
1017 | rc = security_fs_use(newsb); | 1052 | rc = security_fs_use(&selinux_state, newsb); |
1018 | if (rc) | 1053 | if (rc) |
1019 | goto out; | 1054 | goto out; |
1020 | } | 1055 | } |
@@ -1297,7 +1332,7 @@ static inline int default_protocol_dgram(int protocol) | |||
1297 | 1332 | ||
1298 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) | 1333 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) |
1299 | { | 1334 | { |
1300 | int extsockclass = selinux_policycap_extsockclass; | 1335 | int extsockclass = selinux_policycap_extsockclass(); |
1301 | 1336 | ||
1302 | switch (family) { | 1337 | switch (family) { |
1303 | case PF_UNIX: | 1338 | case PF_UNIX: |
@@ -1471,7 +1506,8 @@ static int selinux_genfs_get_sid(struct dentry *dentry, | |||
1471 | path++; | 1506 | path++; |
1472 | } | 1507 | } |
1473 | } | 1508 | } |
1474 | rc = security_genfs_sid(sb->s_type->name, path, tclass, sid); | 1509 | rc = security_genfs_sid(&selinux_state, sb->s_type->name, |
1510 | path, tclass, sid); | ||
1475 | } | 1511 | } |
1476 | free_page((unsigned long)buffer); | 1512 | free_page((unsigned long)buffer); |
1477 | return rc; | 1513 | return rc; |
@@ -1589,7 +1625,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1589 | sid = sbsec->def_sid; | 1625 | sid = sbsec->def_sid; |
1590 | rc = 0; | 1626 | rc = 0; |
1591 | } else { | 1627 | } else { |
1592 | rc = security_context_to_sid_default(context, rc, &sid, | 1628 | rc = security_context_to_sid_default(&selinux_state, |
1629 | context, rc, &sid, | ||
1593 | sbsec->def_sid, | 1630 | sbsec->def_sid, |
1594 | GFP_NOFS); | 1631 | GFP_NOFS); |
1595 | if (rc) { | 1632 | if (rc) { |
@@ -1622,7 +1659,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1622 | sid = sbsec->sid; | 1659 | sid = sbsec->sid; |
1623 | 1660 | ||
1624 | /* Try to obtain a transition SID. */ | 1661 | /* Try to obtain a transition SID. */ |
1625 | rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid); | 1662 | rc = security_transition_sid(&selinux_state, task_sid, sid, |
1663 | sclass, NULL, &sid); | ||
1626 | if (rc) | 1664 | if (rc) |
1627 | goto out; | 1665 | goto out; |
1628 | break; | 1666 | break; |
@@ -1740,9 +1778,11 @@ static int cred_has_capability(const struct cred *cred, | |||
1740 | return -EINVAL; | 1778 | return -EINVAL; |
1741 | } | 1779 | } |
1742 | 1780 | ||
1743 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | 1781 | rc = avc_has_perm_noaudit(&selinux_state, |
1782 | sid, sid, sclass, av, 0, &avd); | ||
1744 | if (audit == SECURITY_CAP_AUDIT) { | 1783 | if (audit == SECURITY_CAP_AUDIT) { |
1745 | int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); | 1784 | int rc2 = avc_audit(&selinux_state, |
1785 | sid, sid, sclass, av, &avd, rc, &ad, 0); | ||
1746 | if (rc2) | 1786 | if (rc2) |
1747 | return rc2; | 1787 | return rc2; |
1748 | } | 1788 | } |
@@ -1768,7 +1808,8 @@ static int inode_has_perm(const struct cred *cred, | |||
1768 | sid = cred_sid(cred); | 1808 | sid = cred_sid(cred); |
1769 | isec = inode->i_security; | 1809 | isec = inode->i_security; |
1770 | 1810 | ||
1771 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); | 1811 | return avc_has_perm(&selinux_state, |
1812 | sid, isec->sid, isec->sclass, perms, adp); | ||
1772 | } | 1813 | } |
1773 | 1814 | ||
1774 | /* Same as inode_has_perm, but pass explicit audit data containing | 1815 | /* Same as inode_has_perm, but pass explicit audit data containing |
@@ -1841,7 +1882,8 @@ static int file_has_perm(const struct cred *cred, | |||
1841 | ad.u.file = file; | 1882 | ad.u.file = file; |
1842 | 1883 | ||
1843 | if (sid != fsec->sid) { | 1884 | if (sid != fsec->sid) { |
1844 | rc = avc_has_perm(sid, fsec->sid, | 1885 | rc = avc_has_perm(&selinux_state, |
1886 | sid, fsec->sid, | ||
1845 | SECCLASS_FD, | 1887 | SECCLASS_FD, |
1846 | FD__USE, | 1888 | FD__USE, |
1847 | &ad); | 1889 | &ad); |
@@ -1883,7 +1925,8 @@ selinux_determine_inode_label(const struct task_security_struct *tsec, | |||
1883 | *_new_isid = tsec->create_sid; | 1925 | *_new_isid = tsec->create_sid; |
1884 | } else { | 1926 | } else { |
1885 | const struct inode_security_struct *dsec = inode_security(dir); | 1927 | const struct inode_security_struct *dsec = inode_security(dir); |
1886 | return security_transition_sid(tsec->sid, dsec->sid, tclass, | 1928 | return security_transition_sid(&selinux_state, tsec->sid, |
1929 | dsec->sid, tclass, | ||
1887 | name, _new_isid); | 1930 | name, _new_isid); |
1888 | } | 1931 | } |
1889 | 1932 | ||
@@ -1910,7 +1953,8 @@ static int may_create(struct inode *dir, | |||
1910 | ad.type = LSM_AUDIT_DATA_DENTRY; | 1953 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1911 | ad.u.dentry = dentry; | 1954 | ad.u.dentry = dentry; |
1912 | 1955 | ||
1913 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1956 | rc = avc_has_perm(&selinux_state, |
1957 | sid, dsec->sid, SECCLASS_DIR, | ||
1914 | DIR__ADD_NAME | DIR__SEARCH, | 1958 | DIR__ADD_NAME | DIR__SEARCH, |
1915 | &ad); | 1959 | &ad); |
1916 | if (rc) | 1960 | if (rc) |
@@ -1921,11 +1965,13 @@ static int may_create(struct inode *dir, | |||
1921 | if (rc) | 1965 | if (rc) |
1922 | return rc; | 1966 | return rc; |
1923 | 1967 | ||
1924 | rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); | 1968 | rc = avc_has_perm(&selinux_state, |
1969 | sid, newsid, tclass, FILE__CREATE, &ad); | ||
1925 | if (rc) | 1970 | if (rc) |
1926 | return rc; | 1971 | return rc; |
1927 | 1972 | ||
1928 | return avc_has_perm(newsid, sbsec->sid, | 1973 | return avc_has_perm(&selinux_state, |
1974 | newsid, sbsec->sid, | ||
1929 | SECCLASS_FILESYSTEM, | 1975 | SECCLASS_FILESYSTEM, |
1930 | FILESYSTEM__ASSOCIATE, &ad); | 1976 | FILESYSTEM__ASSOCIATE, &ad); |
1931 | } | 1977 | } |
@@ -1954,7 +2000,8 @@ static int may_link(struct inode *dir, | |||
1954 | 2000 | ||
1955 | av = DIR__SEARCH; | 2001 | av = DIR__SEARCH; |
1956 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 2002 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
1957 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad); | 2003 | rc = avc_has_perm(&selinux_state, |
2004 | sid, dsec->sid, SECCLASS_DIR, av, &ad); | ||
1958 | if (rc) | 2005 | if (rc) |
1959 | return rc; | 2006 | return rc; |
1960 | 2007 | ||
@@ -1974,7 +2021,8 @@ static int may_link(struct inode *dir, | |||
1974 | return 0; | 2021 | return 0; |
1975 | } | 2022 | } |
1976 | 2023 | ||
1977 | rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); | 2024 | rc = avc_has_perm(&selinux_state, |
2025 | sid, isec->sid, isec->sclass, av, &ad); | ||
1978 | return rc; | 2026 | return rc; |
1979 | } | 2027 | } |
1980 | 2028 | ||
@@ -1998,16 +2046,19 @@ static inline int may_rename(struct inode *old_dir, | |||
1998 | ad.type = LSM_AUDIT_DATA_DENTRY; | 2046 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1999 | 2047 | ||
2000 | ad.u.dentry = old_dentry; | 2048 | ad.u.dentry = old_dentry; |
2001 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 2049 | rc = avc_has_perm(&selinux_state, |
2050 | sid, old_dsec->sid, SECCLASS_DIR, | ||
2002 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); | 2051 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); |
2003 | if (rc) | 2052 | if (rc) |
2004 | return rc; | 2053 | return rc; |
2005 | rc = avc_has_perm(sid, old_isec->sid, | 2054 | rc = avc_has_perm(&selinux_state, |
2055 | sid, old_isec->sid, | ||
2006 | old_isec->sclass, FILE__RENAME, &ad); | 2056 | old_isec->sclass, FILE__RENAME, &ad); |
2007 | if (rc) | 2057 | if (rc) |
2008 | return rc; | 2058 | return rc; |
2009 | if (old_is_dir && new_dir != old_dir) { | 2059 | if (old_is_dir && new_dir != old_dir) { |
2010 | rc = avc_has_perm(sid, old_isec->sid, | 2060 | rc = avc_has_perm(&selinux_state, |
2061 | sid, old_isec->sid, | ||
2011 | old_isec->sclass, DIR__REPARENT, &ad); | 2062 | old_isec->sclass, DIR__REPARENT, &ad); |
2012 | if (rc) | 2063 | if (rc) |
2013 | return rc; | 2064 | return rc; |
@@ -2017,13 +2068,15 @@ static inline int may_rename(struct inode *old_dir, | |||
2017 | av = DIR__ADD_NAME | DIR__SEARCH; | 2068 | av = DIR__ADD_NAME | DIR__SEARCH; |
2018 | if (d_is_positive(new_dentry)) | 2069 | if (d_is_positive(new_dentry)) |
2019 | av |= DIR__REMOVE_NAME; | 2070 | av |= DIR__REMOVE_NAME; |
2020 | rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad); | 2071 | rc = avc_has_perm(&selinux_state, |
2072 | sid, new_dsec->sid, SECCLASS_DIR, av, &ad); | ||
2021 | if (rc) | 2073 | if (rc) |
2022 | return rc; | 2074 | return rc; |
2023 | if (d_is_positive(new_dentry)) { | 2075 | if (d_is_positive(new_dentry)) { |
2024 | new_isec = backing_inode_security(new_dentry); | 2076 | new_isec = backing_inode_security(new_dentry); |
2025 | new_is_dir = d_is_dir(new_dentry); | 2077 | new_is_dir = d_is_dir(new_dentry); |
2026 | rc = avc_has_perm(sid, new_isec->sid, | 2078 | rc = avc_has_perm(&selinux_state, |
2079 | sid, new_isec->sid, | ||
2027 | new_isec->sclass, | 2080 | new_isec->sclass, |
2028 | (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); | 2081 | (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); |
2029 | if (rc) | 2082 | if (rc) |
@@ -2043,7 +2096,8 @@ static int superblock_has_perm(const struct cred *cred, | |||
2043 | u32 sid = cred_sid(cred); | 2096 | u32 sid = cred_sid(cred); |
2044 | 2097 | ||
2045 | sbsec = sb->s_security; | 2098 | sbsec = sb->s_security; |
2046 | return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); | 2099 | return avc_has_perm(&selinux_state, |
2100 | sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); | ||
2047 | } | 2101 | } |
2048 | 2102 | ||
2049 | /* Convert a Linux mode and permission mask to an access vector. */ | 2103 | /* Convert a Linux mode and permission mask to an access vector. */ |
@@ -2106,7 +2160,8 @@ static inline u32 open_file_to_av(struct file *file) | |||
2106 | u32 av = file_to_av(file); | 2160 | u32 av = file_to_av(file); |
2107 | struct inode *inode = file_inode(file); | 2161 | struct inode *inode = file_inode(file); |
2108 | 2162 | ||
2109 | if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC) | 2163 | if (selinux_policycap_openperm() && |
2164 | inode->i_sb->s_magic != SOCKFS_MAGIC) | ||
2110 | av |= FILE__OPEN; | 2165 | av |= FILE__OPEN; |
2111 | 2166 | ||
2112 | return av; | 2167 | return av; |
@@ -2119,7 +2174,8 @@ static int selinux_binder_set_context_mgr(struct task_struct *mgr) | |||
2119 | u32 mysid = current_sid(); | 2174 | u32 mysid = current_sid(); |
2120 | u32 mgrsid = task_sid(mgr); | 2175 | u32 mgrsid = task_sid(mgr); |
2121 | 2176 | ||
2122 | return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, | 2177 | return avc_has_perm(&selinux_state, |
2178 | mysid, mgrsid, SECCLASS_BINDER, | ||
2123 | BINDER__SET_CONTEXT_MGR, NULL); | 2179 | BINDER__SET_CONTEXT_MGR, NULL); |
2124 | } | 2180 | } |
2125 | 2181 | ||
@@ -2132,13 +2188,15 @@ static int selinux_binder_transaction(struct task_struct *from, | |||
2132 | int rc; | 2188 | int rc; |
2133 | 2189 | ||
2134 | if (mysid != fromsid) { | 2190 | if (mysid != fromsid) { |
2135 | rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, | 2191 | rc = avc_has_perm(&selinux_state, |
2192 | mysid, fromsid, SECCLASS_BINDER, | ||
2136 | BINDER__IMPERSONATE, NULL); | 2193 | BINDER__IMPERSONATE, NULL); |
2137 | if (rc) | 2194 | if (rc) |
2138 | return rc; | 2195 | return rc; |
2139 | } | 2196 | } |
2140 | 2197 | ||
2141 | return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, | 2198 | return avc_has_perm(&selinux_state, |
2199 | fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, | ||
2142 | NULL); | 2200 | NULL); |
2143 | } | 2201 | } |
2144 | 2202 | ||
@@ -2148,7 +2206,8 @@ static int selinux_binder_transfer_binder(struct task_struct *from, | |||
2148 | u32 fromsid = task_sid(from); | 2206 | u32 fromsid = task_sid(from); |
2149 | u32 tosid = task_sid(to); | 2207 | u32 tosid = task_sid(to); |
2150 | 2208 | ||
2151 | return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, | 2209 | return avc_has_perm(&selinux_state, |
2210 | fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, | ||
2152 | NULL); | 2211 | NULL); |
2153 | } | 2212 | } |
2154 | 2213 | ||
@@ -2167,7 +2226,8 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2167 | ad.u.path = file->f_path; | 2226 | ad.u.path = file->f_path; |
2168 | 2227 | ||
2169 | if (sid != fsec->sid) { | 2228 | if (sid != fsec->sid) { |
2170 | rc = avc_has_perm(sid, fsec->sid, | 2229 | rc = avc_has_perm(&selinux_state, |
2230 | sid, fsec->sid, | ||
2171 | SECCLASS_FD, | 2231 | SECCLASS_FD, |
2172 | FD__USE, | 2232 | FD__USE, |
2173 | &ad); | 2233 | &ad); |
@@ -2185,7 +2245,8 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2185 | return 0; | 2245 | return 0; |
2186 | 2246 | ||
2187 | isec = backing_inode_security(dentry); | 2247 | isec = backing_inode_security(dentry); |
2188 | return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), | 2248 | return avc_has_perm(&selinux_state, |
2249 | sid, isec->sid, isec->sclass, file_to_av(file), | ||
2189 | &ad); | 2250 | &ad); |
2190 | } | 2251 | } |
2191 | 2252 | ||
@@ -2196,21 +2257,25 @@ static int selinux_ptrace_access_check(struct task_struct *child, | |||
2196 | u32 csid = task_sid(child); | 2257 | u32 csid = task_sid(child); |
2197 | 2258 | ||
2198 | if (mode & PTRACE_MODE_READ) | 2259 | if (mode & PTRACE_MODE_READ) |
2199 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 2260 | return avc_has_perm(&selinux_state, |
2261 | sid, csid, SECCLASS_FILE, FILE__READ, NULL); | ||
2200 | 2262 | ||
2201 | return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); | 2263 | return avc_has_perm(&selinux_state, |
2264 | sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); | ||
2202 | } | 2265 | } |
2203 | 2266 | ||
2204 | static int selinux_ptrace_traceme(struct task_struct *parent) | 2267 | static int selinux_ptrace_traceme(struct task_struct *parent) |
2205 | { | 2268 | { |
2206 | return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS, | 2269 | return avc_has_perm(&selinux_state, |
2270 | task_sid(parent), current_sid(), SECCLASS_PROCESS, | ||
2207 | PROCESS__PTRACE, NULL); | 2271 | PROCESS__PTRACE, NULL); |
2208 | } | 2272 | } |
2209 | 2273 | ||
2210 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 2274 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
2211 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 2275 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
2212 | { | 2276 | { |
2213 | return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS, | 2277 | return avc_has_perm(&selinux_state, |
2278 | current_sid(), task_sid(target), SECCLASS_PROCESS, | ||
2214 | PROCESS__GETCAP, NULL); | 2279 | PROCESS__GETCAP, NULL); |
2215 | } | 2280 | } |
2216 | 2281 | ||
@@ -2219,7 +2284,8 @@ static int selinux_capset(struct cred *new, const struct cred *old, | |||
2219 | const kernel_cap_t *inheritable, | 2284 | const kernel_cap_t *inheritable, |
2220 | const kernel_cap_t *permitted) | 2285 | const kernel_cap_t *permitted) |
2221 | { | 2286 | { |
2222 | return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS, | 2287 | return avc_has_perm(&selinux_state, |
2288 | cred_sid(old), cred_sid(new), SECCLASS_PROCESS, | ||
2223 | PROCESS__SETCAP, NULL); | 2289 | PROCESS__SETCAP, NULL); |
2224 | } | 2290 | } |
2225 | 2291 | ||
@@ -2279,18 +2345,21 @@ static int selinux_syslog(int type) | |||
2279 | switch (type) { | 2345 | switch (type) { |
2280 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ | 2346 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2281 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ | 2347 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2282 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 2348 | return avc_has_perm(&selinux_state, |
2349 | current_sid(), SECINITSID_KERNEL, | ||
2283 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); | 2350 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); |
2284 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ | 2351 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2285 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ | 2352 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2286 | /* Set level of messages printed to console */ | 2353 | /* Set level of messages printed to console */ |
2287 | case SYSLOG_ACTION_CONSOLE_LEVEL: | 2354 | case SYSLOG_ACTION_CONSOLE_LEVEL: |
2288 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 2355 | return avc_has_perm(&selinux_state, |
2356 | current_sid(), SECINITSID_KERNEL, | ||
2289 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, | 2357 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, |
2290 | NULL); | 2358 | NULL); |
2291 | } | 2359 | } |
2292 | /* All other syslog types */ | 2360 | /* All other syslog types */ |
2293 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 2361 | return avc_has_perm(&selinux_state, |
2362 | current_sid(), SECINITSID_KERNEL, | ||
2294 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); | 2363 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); |
2295 | } | 2364 | } |
2296 | 2365 | ||
@@ -2351,13 +2420,14 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, | |||
2351 | * policy allows the corresponding permission between | 2420 | * policy allows the corresponding permission between |
2352 | * the old and new contexts. | 2421 | * the old and new contexts. |
2353 | */ | 2422 | */ |
2354 | if (selinux_policycap_nnp_nosuid_transition) { | 2423 | if (selinux_policycap_nnp_nosuid_transition()) { |
2355 | av = 0; | 2424 | av = 0; |
2356 | if (nnp) | 2425 | if (nnp) |
2357 | av |= PROCESS2__NNP_TRANSITION; | 2426 | av |= PROCESS2__NNP_TRANSITION; |
2358 | if (nosuid) | 2427 | if (nosuid) |
2359 | av |= PROCESS2__NOSUID_TRANSITION; | 2428 | av |= PROCESS2__NOSUID_TRANSITION; |
2360 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2429 | rc = avc_has_perm(&selinux_state, |
2430 | old_tsec->sid, new_tsec->sid, | ||
2361 | SECCLASS_PROCESS2, av, NULL); | 2431 | SECCLASS_PROCESS2, av, NULL); |
2362 | if (!rc) | 2432 | if (!rc) |
2363 | return 0; | 2433 | return 0; |
@@ -2368,7 +2438,8 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, | |||
2368 | * i.e. SIDs that are guaranteed to only be allowed a subset | 2438 | * i.e. SIDs that are guaranteed to only be allowed a subset |
2369 | * of the permissions of the current SID. | 2439 | * of the permissions of the current SID. |
2370 | */ | 2440 | */ |
2371 | rc = security_bounded_transition(old_tsec->sid, new_tsec->sid); | 2441 | rc = security_bounded_transition(&selinux_state, old_tsec->sid, |
2442 | new_tsec->sid); | ||
2372 | if (!rc) | 2443 | if (!rc) |
2373 | return 0; | 2444 | return 0; |
2374 | 2445 | ||
@@ -2420,8 +2491,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2420 | return rc; | 2491 | return rc; |
2421 | } else { | 2492 | } else { |
2422 | /* Check for a default transition on this program. */ | 2493 | /* Check for a default transition on this program. */ |
2423 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 2494 | rc = security_transition_sid(&selinux_state, old_tsec->sid, |
2424 | SECCLASS_PROCESS, NULL, | 2495 | isec->sid, SECCLASS_PROCESS, NULL, |
2425 | &new_tsec->sid); | 2496 | &new_tsec->sid); |
2426 | if (rc) | 2497 | if (rc) |
2427 | return rc; | 2498 | return rc; |
@@ -2439,25 +2510,29 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2439 | ad.u.file = bprm->file; | 2510 | ad.u.file = bprm->file; |
2440 | 2511 | ||
2441 | if (new_tsec->sid == old_tsec->sid) { | 2512 | if (new_tsec->sid == old_tsec->sid) { |
2442 | rc = avc_has_perm(old_tsec->sid, isec->sid, | 2513 | rc = avc_has_perm(&selinux_state, |
2514 | old_tsec->sid, isec->sid, | ||
2443 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); | 2515 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); |
2444 | if (rc) | 2516 | if (rc) |
2445 | return rc; | 2517 | return rc; |
2446 | } else { | 2518 | } else { |
2447 | /* Check permissions for the transition. */ | 2519 | /* Check permissions for the transition. */ |
2448 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2520 | rc = avc_has_perm(&selinux_state, |
2521 | old_tsec->sid, new_tsec->sid, | ||
2449 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); | 2522 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); |
2450 | if (rc) | 2523 | if (rc) |
2451 | return rc; | 2524 | return rc; |
2452 | 2525 | ||
2453 | rc = avc_has_perm(new_tsec->sid, isec->sid, | 2526 | rc = avc_has_perm(&selinux_state, |
2527 | new_tsec->sid, isec->sid, | ||
2454 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); | 2528 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); |
2455 | if (rc) | 2529 | if (rc) |
2456 | return rc; | 2530 | return rc; |
2457 | 2531 | ||
2458 | /* Check for shared state */ | 2532 | /* Check for shared state */ |
2459 | if (bprm->unsafe & LSM_UNSAFE_SHARE) { | 2533 | if (bprm->unsafe & LSM_UNSAFE_SHARE) { |
2460 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2534 | rc = avc_has_perm(&selinux_state, |
2535 | old_tsec->sid, new_tsec->sid, | ||
2461 | SECCLASS_PROCESS, PROCESS__SHARE, | 2536 | SECCLASS_PROCESS, PROCESS__SHARE, |
2462 | NULL); | 2537 | NULL); |
2463 | if (rc) | 2538 | if (rc) |
@@ -2469,7 +2544,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2469 | if (bprm->unsafe & LSM_UNSAFE_PTRACE) { | 2544 | if (bprm->unsafe & LSM_UNSAFE_PTRACE) { |
2470 | u32 ptsid = ptrace_parent_sid(); | 2545 | u32 ptsid = ptrace_parent_sid(); |
2471 | if (ptsid != 0) { | 2546 | if (ptsid != 0) { |
2472 | rc = avc_has_perm(ptsid, new_tsec->sid, | 2547 | rc = avc_has_perm(&selinux_state, |
2548 | ptsid, new_tsec->sid, | ||
2473 | SECCLASS_PROCESS, | 2549 | SECCLASS_PROCESS, |
2474 | PROCESS__PTRACE, NULL); | 2550 | PROCESS__PTRACE, NULL); |
2475 | if (rc) | 2551 | if (rc) |
@@ -2483,7 +2559,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2483 | /* Enable secure mode for SIDs transitions unless | 2559 | /* Enable secure mode for SIDs transitions unless |
2484 | the noatsecure permission is granted between | 2560 | the noatsecure permission is granted between |
2485 | the two SIDs, i.e. ahp returns 0. */ | 2561 | the two SIDs, i.e. ahp returns 0. */ |
2486 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2562 | rc = avc_has_perm(&selinux_state, |
2563 | old_tsec->sid, new_tsec->sid, | ||
2487 | SECCLASS_PROCESS, PROCESS__NOATSECURE, | 2564 | SECCLASS_PROCESS, PROCESS__NOATSECURE, |
2488 | NULL); | 2565 | NULL); |
2489 | bprm->secureexec |= !!rc; | 2566 | bprm->secureexec |= !!rc; |
@@ -2575,7 +2652,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2575 | * higher than the default soft limit for cases where the default is | 2652 | * higher than the default soft limit for cases where the default is |
2576 | * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. | 2653 | * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. |
2577 | */ | 2654 | */ |
2578 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2655 | rc = avc_has_perm(&selinux_state, |
2656 | new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | ||
2579 | PROCESS__RLIMITINH, NULL); | 2657 | PROCESS__RLIMITINH, NULL); |
2580 | if (rc) { | 2658 | if (rc) { |
2581 | /* protect against do_prlimit() */ | 2659 | /* protect against do_prlimit() */ |
@@ -2615,7 +2693,8 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) | |||
2615 | * This must occur _after_ the task SID has been updated so that any | 2693 | * This must occur _after_ the task SID has been updated so that any |
2616 | * kill done after the flush will be checked against the new SID. | 2694 | * kill done after the flush will be checked against the new SID. |
2617 | */ | 2695 | */ |
2618 | rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); | 2696 | rc = avc_has_perm(&selinux_state, |
2697 | osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); | ||
2619 | if (rc) { | 2698 | if (rc) { |
2620 | if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { | 2699 | if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { |
2621 | memset(&itimer, 0, sizeof itimer); | 2700 | memset(&itimer, 0, sizeof itimer); |
@@ -2779,7 +2858,9 @@ static int selinux_sb_remount(struct super_block *sb, void *data) | |||
2779 | 2858 | ||
2780 | if (flags[i] == SBLABEL_MNT) | 2859 | if (flags[i] == SBLABEL_MNT) |
2781 | continue; | 2860 | continue; |
2782 | rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL); | 2861 | rc = security_context_str_to_sid(&selinux_state, |
2862 | mount_options[i], &sid, | ||
2863 | GFP_KERNEL); | ||
2783 | if (rc) { | 2864 | if (rc) { |
2784 | printk(KERN_WARNING "SELinux: security_context_str_to_sid" | 2865 | printk(KERN_WARNING "SELinux: security_context_str_to_sid" |
2785 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 2866 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -2904,7 +2985,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode, | |||
2904 | if (rc) | 2985 | if (rc) |
2905 | return rc; | 2986 | return rc; |
2906 | 2987 | ||
2907 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | 2988 | return security_sid_to_context(&selinux_state, newsid, (char **)ctx, |
2989 | ctxlen); | ||
2908 | } | 2990 | } |
2909 | 2991 | ||
2910 | static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, | 2992 | static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, |
@@ -2958,14 +3040,15 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2958 | isec->initialized = LABEL_INITIALIZED; | 3040 | isec->initialized = LABEL_INITIALIZED; |
2959 | } | 3041 | } |
2960 | 3042 | ||
2961 | if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT)) | 3043 | if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT)) |
2962 | return -EOPNOTSUPP; | 3044 | return -EOPNOTSUPP; |
2963 | 3045 | ||
2964 | if (name) | 3046 | if (name) |
2965 | *name = XATTR_SELINUX_SUFFIX; | 3047 | *name = XATTR_SELINUX_SUFFIX; |
2966 | 3048 | ||
2967 | if (value && len) { | 3049 | if (value && len) { |
2968 | rc = security_sid_to_context_force(newsid, &context, &clen); | 3050 | rc = security_sid_to_context_force(&selinux_state, newsid, |
3051 | &context, &clen); | ||
2969 | if (rc) | 3052 | if (rc) |
2970 | return rc; | 3053 | return rc; |
2971 | *value = context; | 3054 | *value = context; |
@@ -3040,7 +3123,8 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, | |||
3040 | if (IS_ERR(isec)) | 3123 | if (IS_ERR(isec)) |
3041 | return PTR_ERR(isec); | 3124 | return PTR_ERR(isec); |
3042 | 3125 | ||
3043 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad, | 3126 | return avc_has_perm_flags(&selinux_state, |
3127 | sid, isec->sid, isec->sclass, FILE__READ, &ad, | ||
3044 | rcu ? MAY_NOT_BLOCK : 0); | 3128 | rcu ? MAY_NOT_BLOCK : 0); |
3045 | } | 3129 | } |
3046 | 3130 | ||
@@ -3056,7 +3140,8 @@ static noinline int audit_inode_permission(struct inode *inode, | |||
3056 | ad.type = LSM_AUDIT_DATA_INODE; | 3140 | ad.type = LSM_AUDIT_DATA_INODE; |
3057 | ad.u.inode = inode; | 3141 | ad.u.inode = inode; |
3058 | 3142 | ||
3059 | rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, | 3143 | rc = slow_avc_audit(&selinux_state, |
3144 | current_sid(), isec->sid, isec->sclass, perms, | ||
3060 | audited, denied, result, &ad, flags); | 3145 | audited, denied, result, &ad, flags); |
3061 | if (rc) | 3146 | if (rc) |
3062 | return rc; | 3147 | return rc; |
@@ -3094,7 +3179,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
3094 | if (IS_ERR(isec)) | 3179 | if (IS_ERR(isec)) |
3095 | return PTR_ERR(isec); | 3180 | return PTR_ERR(isec); |
3096 | 3181 | ||
3097 | rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); | 3182 | rc = avc_has_perm_noaudit(&selinux_state, |
3183 | sid, isec->sid, isec->sclass, perms, 0, &avd); | ||
3098 | audited = avc_audit_required(perms, &avd, rc, | 3184 | audited = avc_audit_required(perms, &avd, rc, |
3099 | from_access ? FILE__AUDIT_ACCESS : 0, | 3185 | from_access ? FILE__AUDIT_ACCESS : 0, |
3100 | &denied); | 3186 | &denied); |
@@ -3126,7 +3212,7 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
3126 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 3212 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
3127 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | 3213 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
3128 | 3214 | ||
3129 | if (selinux_policycap_openperm && | 3215 | if (selinux_policycap_openperm() && |
3130 | inode->i_sb->s_magic != SOCKFS_MAGIC && | 3216 | inode->i_sb->s_magic != SOCKFS_MAGIC && |
3131 | (ia_valid & ATTR_SIZE) && | 3217 | (ia_valid & ATTR_SIZE) && |
3132 | !(ia_valid & ATTR_FILE)) | 3218 | !(ia_valid & ATTR_FILE)) |
@@ -3183,12 +3269,14 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
3183 | ad.u.dentry = dentry; | 3269 | ad.u.dentry = dentry; |
3184 | 3270 | ||
3185 | isec = backing_inode_security(dentry); | 3271 | isec = backing_inode_security(dentry); |
3186 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 3272 | rc = avc_has_perm(&selinux_state, |
3273 | sid, isec->sid, isec->sclass, | ||
3187 | FILE__RELABELFROM, &ad); | 3274 | FILE__RELABELFROM, &ad); |
3188 | if (rc) | 3275 | if (rc) |
3189 | return rc; | 3276 | return rc; |
3190 | 3277 | ||
3191 | rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); | 3278 | rc = security_context_to_sid(&selinux_state, value, size, &newsid, |
3279 | GFP_KERNEL); | ||
3192 | if (rc == -EINVAL) { | 3280 | if (rc == -EINVAL) { |
3193 | if (!has_cap_mac_admin(true)) { | 3281 | if (!has_cap_mac_admin(true)) { |
3194 | struct audit_buffer *ab; | 3282 | struct audit_buffer *ab; |
@@ -3213,22 +3301,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
3213 | 3301 | ||
3214 | return rc; | 3302 | return rc; |
3215 | } | 3303 | } |
3216 | rc = security_context_to_sid_force(value, size, &newsid); | 3304 | rc = security_context_to_sid_force(&selinux_state, value, |
3305 | size, &newsid); | ||
3217 | } | 3306 | } |
3218 | if (rc) | 3307 | if (rc) |
3219 | return rc; | 3308 | return rc; |
3220 | 3309 | ||
3221 | rc = avc_has_perm(sid, newsid, isec->sclass, | 3310 | rc = avc_has_perm(&selinux_state, |
3311 | sid, newsid, isec->sclass, | ||
3222 | FILE__RELABELTO, &ad); | 3312 | FILE__RELABELTO, &ad); |
3223 | if (rc) | 3313 | if (rc) |
3224 | return rc; | 3314 | return rc; |
3225 | 3315 | ||
3226 | rc = security_validate_transition(isec->sid, newsid, sid, | 3316 | rc = security_validate_transition(&selinux_state, isec->sid, newsid, |
3227 | isec->sclass); | 3317 | sid, isec->sclass); |
3228 | if (rc) | 3318 | if (rc) |
3229 | return rc; | 3319 | return rc; |
3230 | 3320 | ||
3231 | return avc_has_perm(newsid, | 3321 | return avc_has_perm(&selinux_state, |
3322 | newsid, | ||
3232 | sbsec->sid, | 3323 | sbsec->sid, |
3233 | SECCLASS_FILESYSTEM, | 3324 | SECCLASS_FILESYSTEM, |
3234 | FILESYSTEM__ASSOCIATE, | 3325 | FILESYSTEM__ASSOCIATE, |
@@ -3249,7 +3340,8 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
3249 | return; | 3340 | return; |
3250 | } | 3341 | } |
3251 | 3342 | ||
3252 | rc = security_context_to_sid_force(value, size, &newsid); | 3343 | rc = security_context_to_sid_force(&selinux_state, value, size, |
3344 | &newsid); | ||
3253 | if (rc) { | 3345 | if (rc) { |
3254 | printk(KERN_ERR "SELinux: unable to map context to SID" | 3346 | printk(KERN_ERR "SELinux: unable to map context to SID" |
3255 | "for (%s, %lu), rc=%d\n", | 3347 | "for (%s, %lu), rc=%d\n", |
@@ -3324,10 +3416,12 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void | |||
3324 | */ | 3416 | */ |
3325 | isec = inode_security(inode); | 3417 | isec = inode_security(inode); |
3326 | if (has_cap_mac_admin(false)) | 3418 | if (has_cap_mac_admin(false)) |
3327 | error = security_sid_to_context_force(isec->sid, &context, | 3419 | error = security_sid_to_context_force(&selinux_state, |
3420 | isec->sid, &context, | ||
3328 | &size); | 3421 | &size); |
3329 | else | 3422 | else |
3330 | error = security_sid_to_context(isec->sid, &context, &size); | 3423 | error = security_sid_to_context(&selinux_state, isec->sid, |
3424 | &context, &size); | ||
3331 | if (error) | 3425 | if (error) |
3332 | return error; | 3426 | return error; |
3333 | error = size; | 3427 | error = size; |
@@ -3353,7 +3447,8 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
3353 | if (!value || !size) | 3447 | if (!value || !size) |
3354 | return -EACCES; | 3448 | return -EACCES; |
3355 | 3449 | ||
3356 | rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); | 3450 | rc = security_context_to_sid(&selinux_state, value, size, &newsid, |
3451 | GFP_KERNEL); | ||
3357 | if (rc) | 3452 | if (rc) |
3358 | return rc; | 3453 | return rc; |
3359 | 3454 | ||
@@ -3442,7 +3537,7 @@ static int selinux_file_permission(struct file *file, int mask) | |||
3442 | 3537 | ||
3443 | isec = inode_security(inode); | 3538 | isec = inode_security(inode); |
3444 | if (sid == fsec->sid && fsec->isid == isec->sid && | 3539 | if (sid == fsec->sid && fsec->isid == isec->sid && |
3445 | fsec->pseqno == avc_policy_seqno()) | 3540 | fsec->pseqno == avc_policy_seqno(&selinux_state)) |
3446 | /* No change since file_open check. */ | 3541 | /* No change since file_open check. */ |
3447 | return 0; | 3542 | return 0; |
3448 | 3543 | ||
@@ -3482,7 +3577,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
3482 | ad.u.op->path = file->f_path; | 3577 | ad.u.op->path = file->f_path; |
3483 | 3578 | ||
3484 | if (ssid != fsec->sid) { | 3579 | if (ssid != fsec->sid) { |
3485 | rc = avc_has_perm(ssid, fsec->sid, | 3580 | rc = avc_has_perm(&selinux_state, |
3581 | ssid, fsec->sid, | ||
3486 | SECCLASS_FD, | 3582 | SECCLASS_FD, |
3487 | FD__USE, | 3583 | FD__USE, |
3488 | &ad); | 3584 | &ad); |
@@ -3494,8 +3590,9 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
3494 | return 0; | 3590 | return 0; |
3495 | 3591 | ||
3496 | isec = inode_security(inode); | 3592 | isec = inode_security(inode); |
3497 | rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, | 3593 | rc = avc_has_extended_perms(&selinux_state, |
3498 | requested, driver, xperm, &ad); | 3594 | ssid, isec->sid, isec->sclass, |
3595 | requested, driver, xperm, &ad); | ||
3499 | out: | 3596 | out: |
3500 | return rc; | 3597 | return rc; |
3501 | } | 3598 | } |
@@ -3563,7 +3660,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3563 | * private file mapping that will also be writable. | 3660 | * private file mapping that will also be writable. |
3564 | * This has an additional check. | 3661 | * This has an additional check. |
3565 | */ | 3662 | */ |
3566 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, | 3663 | rc = avc_has_perm(&selinux_state, |
3664 | sid, sid, SECCLASS_PROCESS, | ||
3567 | PROCESS__EXECMEM, NULL); | 3665 | PROCESS__EXECMEM, NULL); |
3568 | if (rc) | 3666 | if (rc) |
3569 | goto error; | 3667 | goto error; |
@@ -3593,7 +3691,8 @@ static int selinux_mmap_addr(unsigned long addr) | |||
3593 | 3691 | ||
3594 | if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { | 3692 | if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { |
3595 | u32 sid = current_sid(); | 3693 | u32 sid = current_sid(); |
3596 | rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, | 3694 | rc = avc_has_perm(&selinux_state, |
3695 | sid, sid, SECCLASS_MEMPROTECT, | ||
3597 | MEMPROTECT__MMAP_ZERO, NULL); | 3696 | MEMPROTECT__MMAP_ZERO, NULL); |
3598 | } | 3697 | } |
3599 | 3698 | ||
@@ -3615,7 +3714,7 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot, | |||
3615 | return rc; | 3714 | return rc; |
3616 | } | 3715 | } |
3617 | 3716 | ||
3618 | if (selinux_checkreqprot) | 3717 | if (selinux_state.checkreqprot) |
3619 | prot = reqprot; | 3718 | prot = reqprot; |
3620 | 3719 | ||
3621 | return file_map_prot_check(file, prot, | 3720 | return file_map_prot_check(file, prot, |
@@ -3629,7 +3728,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3629 | const struct cred *cred = current_cred(); | 3728 | const struct cred *cred = current_cred(); |
3630 | u32 sid = cred_sid(cred); | 3729 | u32 sid = cred_sid(cred); |
3631 | 3730 | ||
3632 | if (selinux_checkreqprot) | 3731 | if (selinux_state.checkreqprot) |
3633 | prot = reqprot; | 3732 | prot = reqprot; |
3634 | 3733 | ||
3635 | if (default_noexec && | 3734 | if (default_noexec && |
@@ -3637,13 +3736,15 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3637 | int rc = 0; | 3736 | int rc = 0; |
3638 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3737 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3639 | vma->vm_end <= vma->vm_mm->brk) { | 3738 | vma->vm_end <= vma->vm_mm->brk) { |
3640 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, | 3739 | rc = avc_has_perm(&selinux_state, |
3740 | sid, sid, SECCLASS_PROCESS, | ||
3641 | PROCESS__EXECHEAP, NULL); | 3741 | PROCESS__EXECHEAP, NULL); |
3642 | } else if (!vma->vm_file && | 3742 | } else if (!vma->vm_file && |
3643 | ((vma->vm_start <= vma->vm_mm->start_stack && | 3743 | ((vma->vm_start <= vma->vm_mm->start_stack && |
3644 | vma->vm_end >= vma->vm_mm->start_stack) || | 3744 | vma->vm_end >= vma->vm_mm->start_stack) || |
3645 | vma_is_stack_for_current(vma))) { | 3745 | vma_is_stack_for_current(vma))) { |
3646 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, | 3746 | rc = avc_has_perm(&selinux_state, |
3747 | sid, sid, SECCLASS_PROCESS, | ||
3647 | PROCESS__EXECSTACK, NULL); | 3748 | PROCESS__EXECSTACK, NULL); |
3648 | } else if (vma->vm_file && vma->anon_vma) { | 3749 | } else if (vma->vm_file && vma->anon_vma) { |
3649 | /* | 3750 | /* |
@@ -3735,7 +3836,8 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, | |||
3735 | else | 3836 | else |
3736 | perm = signal_to_av(signum); | 3837 | perm = signal_to_av(signum); |
3737 | 3838 | ||
3738 | return avc_has_perm(fsec->fown_sid, sid, | 3839 | return avc_has_perm(&selinux_state, |
3840 | fsec->fown_sid, sid, | ||
3739 | SECCLASS_PROCESS, perm, NULL); | 3841 | SECCLASS_PROCESS, perm, NULL); |
3740 | } | 3842 | } |
3741 | 3843 | ||
@@ -3761,7 +3863,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred) | |||
3761 | * struct as its SID. | 3863 | * struct as its SID. |
3762 | */ | 3864 | */ |
3763 | fsec->isid = isec->sid; | 3865 | fsec->isid = isec->sid; |
3764 | fsec->pseqno = avc_policy_seqno(); | 3866 | fsec->pseqno = avc_policy_seqno(&selinux_state); |
3765 | /* | 3867 | /* |
3766 | * Since the inode label or policy seqno may have changed | 3868 | * Since the inode label or policy seqno may have changed |
3767 | * between the selinux_inode_permission check and the saving | 3869 | * between the selinux_inode_permission check and the saving |
@@ -3780,7 +3882,8 @@ static int selinux_task_alloc(struct task_struct *task, | |||
3780 | { | 3882 | { |
3781 | u32 sid = current_sid(); | 3883 | u32 sid = current_sid(); |
3782 | 3884 | ||
3783 | return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); | 3885 | return avc_has_perm(&selinux_state, |
3886 | sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); | ||
3784 | } | 3887 | } |
3785 | 3888 | ||
3786 | /* | 3889 | /* |
@@ -3854,7 +3957,8 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) | |||
3854 | u32 sid = current_sid(); | 3957 | u32 sid = current_sid(); |
3855 | int ret; | 3958 | int ret; |
3856 | 3959 | ||
3857 | ret = avc_has_perm(sid, secid, | 3960 | ret = avc_has_perm(&selinux_state, |
3961 | sid, secid, | ||
3858 | SECCLASS_KERNEL_SERVICE, | 3962 | SECCLASS_KERNEL_SERVICE, |
3859 | KERNEL_SERVICE__USE_AS_OVERRIDE, | 3963 | KERNEL_SERVICE__USE_AS_OVERRIDE, |
3860 | NULL); | 3964 | NULL); |
@@ -3878,7 +3982,8 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3878 | u32 sid = current_sid(); | 3982 | u32 sid = current_sid(); |
3879 | int ret; | 3983 | int ret; |
3880 | 3984 | ||
3881 | ret = avc_has_perm(sid, isec->sid, | 3985 | ret = avc_has_perm(&selinux_state, |
3986 | sid, isec->sid, | ||
3882 | SECCLASS_KERNEL_SERVICE, | 3987 | SECCLASS_KERNEL_SERVICE, |
3883 | KERNEL_SERVICE__CREATE_FILES_AS, | 3988 | KERNEL_SERVICE__CREATE_FILES_AS, |
3884 | NULL); | 3989 | NULL); |
@@ -3895,7 +4000,8 @@ static int selinux_kernel_module_request(char *kmod_name) | |||
3895 | ad.type = LSM_AUDIT_DATA_KMOD; | 4000 | ad.type = LSM_AUDIT_DATA_KMOD; |
3896 | ad.u.kmod_name = kmod_name; | 4001 | ad.u.kmod_name = kmod_name; |
3897 | 4002 | ||
3898 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, | 4003 | return avc_has_perm(&selinux_state, |
4004 | current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, | ||
3899 | SYSTEM__MODULE_REQUEST, &ad); | 4005 | SYSTEM__MODULE_REQUEST, &ad); |
3900 | } | 4006 | } |
3901 | 4007 | ||
@@ -3909,7 +4015,8 @@ static int selinux_kernel_module_from_file(struct file *file) | |||
3909 | 4015 | ||
3910 | /* init_module */ | 4016 | /* init_module */ |
3911 | if (file == NULL) | 4017 | if (file == NULL) |
3912 | return avc_has_perm(sid, sid, SECCLASS_SYSTEM, | 4018 | return avc_has_perm(&selinux_state, |
4019 | sid, sid, SECCLASS_SYSTEM, | ||
3913 | SYSTEM__MODULE_LOAD, NULL); | 4020 | SYSTEM__MODULE_LOAD, NULL); |
3914 | 4021 | ||
3915 | /* finit_module */ | 4022 | /* finit_module */ |
@@ -3919,13 +4026,15 @@ static int selinux_kernel_module_from_file(struct file *file) | |||
3919 | 4026 | ||
3920 | fsec = file->f_security; | 4027 | fsec = file->f_security; |
3921 | if (sid != fsec->sid) { | 4028 | if (sid != fsec->sid) { |
3922 | rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); | 4029 | rc = avc_has_perm(&selinux_state, |
4030 | sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); | ||
3923 | if (rc) | 4031 | if (rc) |
3924 | return rc; | 4032 | return rc; |
3925 | } | 4033 | } |
3926 | 4034 | ||
3927 | isec = inode_security(file_inode(file)); | 4035 | isec = inode_security(file_inode(file)); |
3928 | return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, | 4036 | return avc_has_perm(&selinux_state, |
4037 | sid, isec->sid, SECCLASS_SYSTEM, | ||
3929 | SYSTEM__MODULE_LOAD, &ad); | 4038 | SYSTEM__MODULE_LOAD, &ad); |
3930 | } | 4039 | } |
3931 | 4040 | ||
@@ -3947,19 +4056,22 @@ static int selinux_kernel_read_file(struct file *file, | |||
3947 | 4056 | ||
3948 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 4057 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3949 | { | 4058 | { |
3950 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4059 | return avc_has_perm(&selinux_state, |
4060 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3951 | PROCESS__SETPGID, NULL); | 4061 | PROCESS__SETPGID, NULL); |
3952 | } | 4062 | } |
3953 | 4063 | ||
3954 | static int selinux_task_getpgid(struct task_struct *p) | 4064 | static int selinux_task_getpgid(struct task_struct *p) |
3955 | { | 4065 | { |
3956 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4066 | return avc_has_perm(&selinux_state, |
4067 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3957 | PROCESS__GETPGID, NULL); | 4068 | PROCESS__GETPGID, NULL); |
3958 | } | 4069 | } |
3959 | 4070 | ||
3960 | static int selinux_task_getsid(struct task_struct *p) | 4071 | static int selinux_task_getsid(struct task_struct *p) |
3961 | { | 4072 | { |
3962 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4073 | return avc_has_perm(&selinux_state, |
4074 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3963 | PROCESS__GETSESSION, NULL); | 4075 | PROCESS__GETSESSION, NULL); |
3964 | } | 4076 | } |
3965 | 4077 | ||
@@ -3970,19 +4082,22 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | |||
3970 | 4082 | ||
3971 | static int selinux_task_setnice(struct task_struct *p, int nice) | 4083 | static int selinux_task_setnice(struct task_struct *p, int nice) |
3972 | { | 4084 | { |
3973 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4085 | return avc_has_perm(&selinux_state, |
4086 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3974 | PROCESS__SETSCHED, NULL); | 4087 | PROCESS__SETSCHED, NULL); |
3975 | } | 4088 | } |
3976 | 4089 | ||
3977 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 4090 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) |
3978 | { | 4091 | { |
3979 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4092 | return avc_has_perm(&selinux_state, |
4093 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3980 | PROCESS__SETSCHED, NULL); | 4094 | PROCESS__SETSCHED, NULL); |
3981 | } | 4095 | } |
3982 | 4096 | ||
3983 | static int selinux_task_getioprio(struct task_struct *p) | 4097 | static int selinux_task_getioprio(struct task_struct *p) |
3984 | { | 4098 | { |
3985 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4099 | return avc_has_perm(&selinux_state, |
4100 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
3986 | PROCESS__GETSCHED, NULL); | 4101 | PROCESS__GETSCHED, NULL); |
3987 | } | 4102 | } |
3988 | 4103 | ||
@@ -3997,7 +4112,8 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre | |||
3997 | av |= PROCESS__SETRLIMIT; | 4112 | av |= PROCESS__SETRLIMIT; |
3998 | if (flags & LSM_PRLIMIT_READ) | 4113 | if (flags & LSM_PRLIMIT_READ) |
3999 | av |= PROCESS__GETRLIMIT; | 4114 | av |= PROCESS__GETRLIMIT; |
4000 | return avc_has_perm(cred_sid(cred), cred_sid(tcred), | 4115 | return avc_has_perm(&selinux_state, |
4116 | cred_sid(cred), cred_sid(tcred), | ||
4001 | SECCLASS_PROCESS, av, NULL); | 4117 | SECCLASS_PROCESS, av, NULL); |
4002 | } | 4118 | } |
4003 | 4119 | ||
@@ -4011,7 +4127,8 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | |||
4011 | later be used as a safe reset point for the soft limit | 4127 | later be used as a safe reset point for the soft limit |
4012 | upon context transitions. See selinux_bprm_committing_creds. */ | 4128 | upon context transitions. See selinux_bprm_committing_creds. */ |
4013 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 4129 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
4014 | return avc_has_perm(current_sid(), task_sid(p), | 4130 | return avc_has_perm(&selinux_state, |
4131 | current_sid(), task_sid(p), | ||
4015 | SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); | 4132 | SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); |
4016 | 4133 | ||
4017 | return 0; | 4134 | return 0; |
@@ -4019,19 +4136,22 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | |||
4019 | 4136 | ||
4020 | static int selinux_task_setscheduler(struct task_struct *p) | 4137 | static int selinux_task_setscheduler(struct task_struct *p) |
4021 | { | 4138 | { |
4022 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4139 | return avc_has_perm(&selinux_state, |
4140 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
4023 | PROCESS__SETSCHED, NULL); | 4141 | PROCESS__SETSCHED, NULL); |
4024 | } | 4142 | } |
4025 | 4143 | ||
4026 | static int selinux_task_getscheduler(struct task_struct *p) | 4144 | static int selinux_task_getscheduler(struct task_struct *p) |
4027 | { | 4145 | { |
4028 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4146 | return avc_has_perm(&selinux_state, |
4147 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
4029 | PROCESS__GETSCHED, NULL); | 4148 | PROCESS__GETSCHED, NULL); |
4030 | } | 4149 | } |
4031 | 4150 | ||
4032 | static int selinux_task_movememory(struct task_struct *p) | 4151 | static int selinux_task_movememory(struct task_struct *p) |
4033 | { | 4152 | { |
4034 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, | 4153 | return avc_has_perm(&selinux_state, |
4154 | current_sid(), task_sid(p), SECCLASS_PROCESS, | ||
4035 | PROCESS__SETSCHED, NULL); | 4155 | PROCESS__SETSCHED, NULL); |
4036 | } | 4156 | } |
4037 | 4157 | ||
@@ -4046,7 +4166,8 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, | |||
4046 | perm = signal_to_av(sig); | 4166 | perm = signal_to_av(sig); |
4047 | if (!secid) | 4167 | if (!secid) |
4048 | secid = current_sid(); | 4168 | secid = current_sid(); |
4049 | return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); | 4169 | return avc_has_perm(&selinux_state, |
4170 | secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); | ||
4050 | } | 4171 | } |
4051 | 4172 | ||
4052 | static void selinux_task_to_inode(struct task_struct *p, | 4173 | static void selinux_task_to_inode(struct task_struct *p, |
@@ -4134,6 +4255,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, | |||
4134 | break; | 4255 | break; |
4135 | } | 4256 | } |
4136 | 4257 | ||
4258 | #if IS_ENABLED(CONFIG_IP_SCTP) | ||
4259 | case IPPROTO_SCTP: { | ||
4260 | struct sctphdr _sctph, *sh; | ||
4261 | |||
4262 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
4263 | break; | ||
4264 | |||
4265 | offset += ihlen; | ||
4266 | sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); | ||
4267 | if (sh == NULL) | ||
4268 | break; | ||
4269 | |||
4270 | ad->u.net->sport = sh->source; | ||
4271 | ad->u.net->dport = sh->dest; | ||
4272 | break; | ||
4273 | } | ||
4274 | #endif | ||
4137 | default: | 4275 | default: |
4138 | break; | 4276 | break; |
4139 | } | 4277 | } |
@@ -4207,6 +4345,19 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, | |||
4207 | break; | 4345 | break; |
4208 | } | 4346 | } |
4209 | 4347 | ||
4348 | #if IS_ENABLED(CONFIG_IP_SCTP) | ||
4349 | case IPPROTO_SCTP: { | ||
4350 | struct sctphdr _sctph, *sh; | ||
4351 | |||
4352 | sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); | ||
4353 | if (sh == NULL) | ||
4354 | break; | ||
4355 | |||
4356 | ad->u.net->sport = sh->source; | ||
4357 | ad->u.net->dport = sh->dest; | ||
4358 | break; | ||
4359 | } | ||
4360 | #endif | ||
4210 | /* includes fragments */ | 4361 | /* includes fragments */ |
4211 | default: | 4362 | default: |
4212 | break; | 4363 | break; |
@@ -4287,7 +4438,8 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
4287 | if (unlikely(err)) | 4438 | if (unlikely(err)) |
4288 | return -EACCES; | 4439 | return -EACCES; |
4289 | 4440 | ||
4290 | err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); | 4441 | err = security_net_peersid_resolve(&selinux_state, nlbl_sid, |
4442 | nlbl_type, xfrm_sid, sid); | ||
4291 | if (unlikely(err)) { | 4443 | if (unlikely(err)) { |
4292 | printk(KERN_WARNING | 4444 | printk(KERN_WARNING |
4293 | "SELinux: failure in selinux_skb_peerlbl_sid()," | 4445 | "SELinux: failure in selinux_skb_peerlbl_sid()," |
@@ -4315,7 +4467,8 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) | |||
4315 | int err = 0; | 4467 | int err = 0; |
4316 | 4468 | ||
4317 | if (skb_sid != SECSID_NULL) | 4469 | if (skb_sid != SECSID_NULL) |
4318 | err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); | 4470 | err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid, |
4471 | conn_sid); | ||
4319 | else | 4472 | else |
4320 | *conn_sid = sk_sid; | 4473 | *conn_sid = sk_sid; |
4321 | 4474 | ||
@@ -4332,8 +4485,8 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, | |||
4332 | return 0; | 4485 | return 0; |
4333 | } | 4486 | } |
4334 | 4487 | ||
4335 | return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, | 4488 | return security_transition_sid(&selinux_state, tsec->sid, tsec->sid, |
4336 | socksid); | 4489 | secclass, NULL, socksid); |
4337 | } | 4490 | } |
4338 | 4491 | ||
4339 | static int sock_has_perm(struct sock *sk, u32 perms) | 4492 | static int sock_has_perm(struct sock *sk, u32 perms) |
@@ -4349,7 +4502,8 @@ static int sock_has_perm(struct sock *sk, u32 perms) | |||
4349 | ad.u.net = &net; | 4502 | ad.u.net = &net; |
4350 | ad.u.net->sk = sk; | 4503 | ad.u.net->sk = sk; |
4351 | 4504 | ||
4352 | return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, | 4505 | return avc_has_perm(&selinux_state, |
4506 | current_sid(), sksec->sid, sksec->sclass, perms, | ||
4353 | &ad); | 4507 | &ad); |
4354 | } | 4508 | } |
4355 | 4509 | ||
@@ -4369,7 +4523,8 @@ static int selinux_socket_create(int family, int type, | |||
4369 | if (rc) | 4523 | if (rc) |
4370 | return rc; | 4524 | return rc; |
4371 | 4525 | ||
4372 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); | 4526 | return avc_has_perm(&selinux_state, |
4527 | tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); | ||
4373 | } | 4528 | } |
4374 | 4529 | ||
4375 | static int selinux_socket_post_create(struct socket *sock, int family, | 4530 | static int selinux_socket_post_create(struct socket *sock, int family, |
@@ -4396,6 +4551,10 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
4396 | sksec = sock->sk->sk_security; | 4551 | sksec = sock->sk->sk_security; |
4397 | sksec->sclass = sclass; | 4552 | sksec->sclass = sclass; |
4398 | sksec->sid = sid; | 4553 | sksec->sid = sid; |
4554 | /* Allows detection of the first association on this socket */ | ||
4555 | if (sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
4556 | sksec->sctp_assoc_state = SCTP_ASSOC_UNSET; | ||
4557 | |||
4399 | err = selinux_netlbl_socket_post_create(sock->sk, family); | 4558 | err = selinux_netlbl_socket_post_create(sock->sk, family); |
4400 | } | 4559 | } |
4401 | 4560 | ||
@@ -4416,11 +4575,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4416 | if (err) | 4575 | if (err) |
4417 | goto out; | 4576 | goto out; |
4418 | 4577 | ||
4419 | /* | 4578 | /* If PF_INET or PF_INET6, check name_bind permission for the port. */ |
4420 | * If PF_INET or PF_INET6, check name_bind permission for the port. | ||
4421 | * Multiple address binding for SCTP is not supported yet: we just | ||
4422 | * check the first address now. | ||
4423 | */ | ||
4424 | family = sk->sk_family; | 4579 | family = sk->sk_family; |
4425 | if (family == PF_INET || family == PF_INET6) { | 4580 | if (family == PF_INET || family == PF_INET6) { |
4426 | char *addrp; | 4581 | char *addrp; |
@@ -4432,22 +4587,35 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4432 | unsigned short snum; | 4587 | unsigned short snum; |
4433 | u32 sid, node_perm; | 4588 | u32 sid, node_perm; |
4434 | 4589 | ||
4435 | if (family == PF_INET) { | 4590 | /* |
4436 | if (addrlen < sizeof(struct sockaddr_in)) { | 4591 | * sctp_bindx(3) calls via selinux_sctp_bind_connect() |
4437 | err = -EINVAL; | 4592 | * that validates multiple binding addresses. Because of this |
4438 | goto out; | 4593 | * need to check address->sa_family as it is possible to have |
4439 | } | 4594 | * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. |
4595 | */ | ||
4596 | switch (address->sa_family) { | ||
4597 | case AF_INET: | ||
4598 | if (addrlen < sizeof(struct sockaddr_in)) | ||
4599 | return -EINVAL; | ||
4440 | addr4 = (struct sockaddr_in *)address; | 4600 | addr4 = (struct sockaddr_in *)address; |
4441 | snum = ntohs(addr4->sin_port); | 4601 | snum = ntohs(addr4->sin_port); |
4442 | addrp = (char *)&addr4->sin_addr.s_addr; | 4602 | addrp = (char *)&addr4->sin_addr.s_addr; |
4443 | } else { | 4603 | break; |
4444 | if (addrlen < SIN6_LEN_RFC2133) { | 4604 | case AF_INET6: |
4445 | err = -EINVAL; | 4605 | if (addrlen < SIN6_LEN_RFC2133) |
4446 | goto out; | 4606 | return -EINVAL; |
4447 | } | ||
4448 | addr6 = (struct sockaddr_in6 *)address; | 4607 | addr6 = (struct sockaddr_in6 *)address; |
4449 | snum = ntohs(addr6->sin6_port); | 4608 | snum = ntohs(addr6->sin6_port); |
4450 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 4609 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
4610 | break; | ||
4611 | default: | ||
4612 | /* Note that SCTP services expect -EINVAL, whereas | ||
4613 | * others expect -EAFNOSUPPORT. | ||
4614 | */ | ||
4615 | if (sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
4616 | return -EINVAL; | ||
4617 | else | ||
4618 | return -EAFNOSUPPORT; | ||
4451 | } | 4619 | } |
4452 | 4620 | ||
4453 | if (snum) { | 4621 | if (snum) { |
@@ -4465,7 +4633,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4465 | ad.u.net = &net; | 4633 | ad.u.net = &net; |
4466 | ad.u.net->sport = htons(snum); | 4634 | ad.u.net->sport = htons(snum); |
4467 | ad.u.net->family = family; | 4635 | ad.u.net->family = family; |
4468 | err = avc_has_perm(sksec->sid, sid, | 4636 | err = avc_has_perm(&selinux_state, |
4637 | sksec->sid, sid, | ||
4469 | sksec->sclass, | 4638 | sksec->sclass, |
4470 | SOCKET__NAME_BIND, &ad); | 4639 | SOCKET__NAME_BIND, &ad); |
4471 | if (err) | 4640 | if (err) |
@@ -4486,6 +4655,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4486 | node_perm = DCCP_SOCKET__NODE_BIND; | 4655 | node_perm = DCCP_SOCKET__NODE_BIND; |
4487 | break; | 4656 | break; |
4488 | 4657 | ||
4658 | case SECCLASS_SCTP_SOCKET: | ||
4659 | node_perm = SCTP_SOCKET__NODE_BIND; | ||
4660 | break; | ||
4661 | |||
4489 | default: | 4662 | default: |
4490 | node_perm = RAWIP_SOCKET__NODE_BIND; | 4663 | node_perm = RAWIP_SOCKET__NODE_BIND; |
4491 | break; | 4664 | break; |
@@ -4500,12 +4673,13 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4500 | ad.u.net->sport = htons(snum); | 4673 | ad.u.net->sport = htons(snum); |
4501 | ad.u.net->family = family; | 4674 | ad.u.net->family = family; |
4502 | 4675 | ||
4503 | if (family == PF_INET) | 4676 | if (address->sa_family == AF_INET) |
4504 | ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; | 4677 | ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; |
4505 | else | 4678 | else |
4506 | ad.u.net->v6info.saddr = addr6->sin6_addr; | 4679 | ad.u.net->v6info.saddr = addr6->sin6_addr; |
4507 | 4680 | ||
4508 | err = avc_has_perm(sksec->sid, sid, | 4681 | err = avc_has_perm(&selinux_state, |
4682 | sksec->sid, sid, | ||
4509 | sksec->sclass, node_perm, &ad); | 4683 | sksec->sclass, node_perm, &ad); |
4510 | if (err) | 4684 | if (err) |
4511 | goto out; | 4685 | goto out; |
@@ -4514,7 +4688,11 @@ out: | |||
4514 | return err; | 4688 | return err; |
4515 | } | 4689 | } |
4516 | 4690 | ||
4517 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 4691 | /* This supports connect(2) and SCTP connect services such as sctp_connectx(3) |
4692 | * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt | ||
4693 | */ | ||
4694 | static int selinux_socket_connect_helper(struct socket *sock, | ||
4695 | struct sockaddr *address, int addrlen) | ||
4518 | { | 4696 | { |
4519 | struct sock *sk = sock->sk; | 4697 | struct sock *sk = sock->sk; |
4520 | struct sk_security_struct *sksec = sk->sk_security; | 4698 | struct sk_security_struct *sksec = sk->sk_security; |
@@ -4525,10 +4703,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
4525 | return err; | 4703 | return err; |
4526 | 4704 | ||
4527 | /* | 4705 | /* |
4528 | * If a TCP or DCCP socket, check name_connect permission for the port. | 4706 | * If a TCP, DCCP or SCTP socket, check name_connect permission |
4707 | * for the port. | ||
4529 | */ | 4708 | */ |
4530 | if (sksec->sclass == SECCLASS_TCP_SOCKET || | 4709 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
4531 | sksec->sclass == SECCLASS_DCCP_SOCKET) { | 4710 | sksec->sclass == SECCLASS_DCCP_SOCKET || |
4711 | sksec->sclass == SECCLASS_SCTP_SOCKET) { | ||
4532 | struct common_audit_data ad; | 4712 | struct common_audit_data ad; |
4533 | struct lsm_network_audit net = {0,}; | 4713 | struct lsm_network_audit net = {0,}; |
4534 | struct sockaddr_in *addr4 = NULL; | 4714 | struct sockaddr_in *addr4 = NULL; |
@@ -4536,38 +4716,75 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
4536 | unsigned short snum; | 4716 | unsigned short snum; |
4537 | u32 sid, perm; | 4717 | u32 sid, perm; |
4538 | 4718 | ||
4539 | if (sk->sk_family == PF_INET) { | 4719 | /* sctp_connectx(3) calls via selinux_sctp_bind_connect() |
4720 | * that validates multiple connect addresses. Because of this | ||
4721 | * need to check address->sa_family as it is possible to have | ||
4722 | * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. | ||
4723 | */ | ||
4724 | switch (address->sa_family) { | ||
4725 | case AF_INET: | ||
4540 | addr4 = (struct sockaddr_in *)address; | 4726 | addr4 = (struct sockaddr_in *)address; |
4541 | if (addrlen < sizeof(struct sockaddr_in)) | 4727 | if (addrlen < sizeof(struct sockaddr_in)) |
4542 | return -EINVAL; | 4728 | return -EINVAL; |
4543 | snum = ntohs(addr4->sin_port); | 4729 | snum = ntohs(addr4->sin_port); |
4544 | } else { | 4730 | break; |
4731 | case AF_INET6: | ||
4545 | addr6 = (struct sockaddr_in6 *)address; | 4732 | addr6 = (struct sockaddr_in6 *)address; |
4546 | if (addrlen < SIN6_LEN_RFC2133) | 4733 | if (addrlen < SIN6_LEN_RFC2133) |
4547 | return -EINVAL; | 4734 | return -EINVAL; |
4548 | snum = ntohs(addr6->sin6_port); | 4735 | snum = ntohs(addr6->sin6_port); |
4736 | break; | ||
4737 | default: | ||
4738 | /* Note that SCTP services expect -EINVAL, whereas | ||
4739 | * others expect -EAFNOSUPPORT. | ||
4740 | */ | ||
4741 | if (sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
4742 | return -EINVAL; | ||
4743 | else | ||
4744 | return -EAFNOSUPPORT; | ||
4549 | } | 4745 | } |
4550 | 4746 | ||
4551 | err = sel_netport_sid(sk->sk_protocol, snum, &sid); | 4747 | err = sel_netport_sid(sk->sk_protocol, snum, &sid); |
4552 | if (err) | 4748 | if (err) |
4553 | goto out; | 4749 | return err; |
4554 | 4750 | ||
4555 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? | 4751 | switch (sksec->sclass) { |
4556 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 4752 | case SECCLASS_TCP_SOCKET: |
4753 | perm = TCP_SOCKET__NAME_CONNECT; | ||
4754 | break; | ||
4755 | case SECCLASS_DCCP_SOCKET: | ||
4756 | perm = DCCP_SOCKET__NAME_CONNECT; | ||
4757 | break; | ||
4758 | case SECCLASS_SCTP_SOCKET: | ||
4759 | perm = SCTP_SOCKET__NAME_CONNECT; | ||
4760 | break; | ||
4761 | } | ||
4557 | 4762 | ||
4558 | ad.type = LSM_AUDIT_DATA_NET; | 4763 | ad.type = LSM_AUDIT_DATA_NET; |
4559 | ad.u.net = &net; | 4764 | ad.u.net = &net; |
4560 | ad.u.net->dport = htons(snum); | 4765 | ad.u.net->dport = htons(snum); |
4561 | ad.u.net->family = sk->sk_family; | 4766 | ad.u.net->family = sk->sk_family; |
4562 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); | 4767 | err = avc_has_perm(&selinux_state, |
4768 | sksec->sid, sid, sksec->sclass, perm, &ad); | ||
4563 | if (err) | 4769 | if (err) |
4564 | goto out; | 4770 | return err; |
4565 | } | 4771 | } |
4566 | 4772 | ||
4567 | err = selinux_netlbl_socket_connect(sk, address); | 4773 | return 0; |
4774 | } | ||
4568 | 4775 | ||
4569 | out: | 4776 | /* Supports connect(2), see comments in selinux_socket_connect_helper() */ |
4570 | return err; | 4777 | static int selinux_socket_connect(struct socket *sock, |
4778 | struct sockaddr *address, int addrlen) | ||
4779 | { | ||
4780 | int err; | ||
4781 | struct sock *sk = sock->sk; | ||
4782 | |||
4783 | err = selinux_socket_connect_helper(sock, address, addrlen); | ||
4784 | if (err) | ||
4785 | return err; | ||
4786 | |||
4787 | return selinux_netlbl_socket_connect(sk, address); | ||
4571 | } | 4788 | } |
4572 | 4789 | ||
4573 | static int selinux_socket_listen(struct socket *sock, int backlog) | 4790 | static int selinux_socket_listen(struct socket *sock, int backlog) |
@@ -4660,7 +4877,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, | |||
4660 | ad.u.net = &net; | 4877 | ad.u.net = &net; |
4661 | ad.u.net->sk = other; | 4878 | ad.u.net->sk = other; |
4662 | 4879 | ||
4663 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, | 4880 | err = avc_has_perm(&selinux_state, |
4881 | sksec_sock->sid, sksec_other->sid, | ||
4664 | sksec_other->sclass, | 4882 | sksec_other->sclass, |
4665 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 4883 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
4666 | if (err) | 4884 | if (err) |
@@ -4668,8 +4886,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, | |||
4668 | 4886 | ||
4669 | /* server child socket */ | 4887 | /* server child socket */ |
4670 | sksec_new->peer_sid = sksec_sock->sid; | 4888 | sksec_new->peer_sid = sksec_sock->sid; |
4671 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, | 4889 | err = security_sid_mls_copy(&selinux_state, sksec_other->sid, |
4672 | &sksec_new->sid); | 4890 | sksec_sock->sid, &sksec_new->sid); |
4673 | if (err) | 4891 | if (err) |
4674 | return err; | 4892 | return err; |
4675 | 4893 | ||
@@ -4691,7 +4909,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4691 | ad.u.net = &net; | 4909 | ad.u.net = &net; |
4692 | ad.u.net->sk = other->sk; | 4910 | ad.u.net->sk = other->sk; |
4693 | 4911 | ||
4694 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, | 4912 | return avc_has_perm(&selinux_state, |
4913 | ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, | ||
4695 | &ad); | 4914 | &ad); |
4696 | } | 4915 | } |
4697 | 4916 | ||
@@ -4706,7 +4925,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, | |||
4706 | err = sel_netif_sid(ns, ifindex, &if_sid); | 4925 | err = sel_netif_sid(ns, ifindex, &if_sid); |
4707 | if (err) | 4926 | if (err) |
4708 | return err; | 4927 | return err; |
4709 | err = avc_has_perm(peer_sid, if_sid, | 4928 | err = avc_has_perm(&selinux_state, |
4929 | peer_sid, if_sid, | ||
4710 | SECCLASS_NETIF, NETIF__INGRESS, ad); | 4930 | SECCLASS_NETIF, NETIF__INGRESS, ad); |
4711 | if (err) | 4931 | if (err) |
4712 | return err; | 4932 | return err; |
@@ -4714,7 +4934,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, | |||
4714 | err = sel_netnode_sid(addrp, family, &node_sid); | 4934 | err = sel_netnode_sid(addrp, family, &node_sid); |
4715 | if (err) | 4935 | if (err) |
4716 | return err; | 4936 | return err; |
4717 | return avc_has_perm(peer_sid, node_sid, | 4937 | return avc_has_perm(&selinux_state, |
4938 | peer_sid, node_sid, | ||
4718 | SECCLASS_NODE, NODE__RECVFROM, ad); | 4939 | SECCLASS_NODE, NODE__RECVFROM, ad); |
4719 | } | 4940 | } |
4720 | 4941 | ||
@@ -4737,7 +4958,8 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4737 | return err; | 4958 | return err; |
4738 | 4959 | ||
4739 | if (selinux_secmark_enabled()) { | 4960 | if (selinux_secmark_enabled()) { |
4740 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 4961 | err = avc_has_perm(&selinux_state, |
4962 | sk_sid, skb->secmark, SECCLASS_PACKET, | ||
4741 | PACKET__RECV, &ad); | 4963 | PACKET__RECV, &ad); |
4742 | if (err) | 4964 | if (err) |
4743 | return err; | 4965 | return err; |
@@ -4774,7 +4996,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4774 | * to the selinux_sock_rcv_skb_compat() function to deal with the | 4996 | * to the selinux_sock_rcv_skb_compat() function to deal with the |
4775 | * special handling. We do this in an attempt to keep this function | 4997 | * special handling. We do this in an attempt to keep this function |
4776 | * as fast and as clean as possible. */ | 4998 | * as fast and as clean as possible. */ |
4777 | if (!selinux_policycap_netpeer) | 4999 | if (!selinux_policycap_netpeer()) |
4778 | return selinux_sock_rcv_skb_compat(sk, skb, family); | 5000 | return selinux_sock_rcv_skb_compat(sk, skb, family); |
4779 | 5001 | ||
4780 | secmark_active = selinux_secmark_enabled(); | 5002 | secmark_active = selinux_secmark_enabled(); |
@@ -4802,7 +5024,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4802 | selinux_netlbl_err(skb, family, err, 0); | 5024 | selinux_netlbl_err(skb, family, err, 0); |
4803 | return err; | 5025 | return err; |
4804 | } | 5026 | } |
4805 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, | 5027 | err = avc_has_perm(&selinux_state, |
5028 | sk_sid, peer_sid, SECCLASS_PEER, | ||
4806 | PEER__RECV, &ad); | 5029 | PEER__RECV, &ad); |
4807 | if (err) { | 5030 | if (err) { |
4808 | selinux_netlbl_err(skb, family, err, 0); | 5031 | selinux_netlbl_err(skb, family, err, 0); |
@@ -4811,7 +5034,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4811 | } | 5034 | } |
4812 | 5035 | ||
4813 | if (secmark_active) { | 5036 | if (secmark_active) { |
4814 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 5037 | err = avc_has_perm(&selinux_state, |
5038 | sk_sid, skb->secmark, SECCLASS_PACKET, | ||
4815 | PACKET__RECV, &ad); | 5039 | PACKET__RECV, &ad); |
4816 | if (err) | 5040 | if (err) |
4817 | return err; | 5041 | return err; |
@@ -4830,12 +5054,14 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4830 | u32 peer_sid = SECSID_NULL; | 5054 | u32 peer_sid = SECSID_NULL; |
4831 | 5055 | ||
4832 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 5056 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4833 | sksec->sclass == SECCLASS_TCP_SOCKET) | 5057 | sksec->sclass == SECCLASS_TCP_SOCKET || |
5058 | sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
4834 | peer_sid = sksec->peer_sid; | 5059 | peer_sid = sksec->peer_sid; |
4835 | if (peer_sid == SECSID_NULL) | 5060 | if (peer_sid == SECSID_NULL) |
4836 | return -ENOPROTOOPT; | 5061 | return -ENOPROTOOPT; |
4837 | 5062 | ||
4838 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 5063 | err = security_sid_to_context(&selinux_state, peer_sid, &scontext, |
5064 | &scontext_len); | ||
4839 | if (err) | 5065 | if (err) |
4840 | return err; | 5066 | return err; |
4841 | 5067 | ||
@@ -4943,6 +5169,172 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) | |||
4943 | sksec->sclass = isec->sclass; | 5169 | sksec->sclass = isec->sclass; |
4944 | } | 5170 | } |
4945 | 5171 | ||
5172 | /* Called whenever SCTP receives an INIT chunk. This happens when an incoming | ||
5173 | * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association | ||
5174 | * already present). | ||
5175 | */ | ||
5176 | static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, | ||
5177 | struct sk_buff *skb) | ||
5178 | { | ||
5179 | struct sk_security_struct *sksec = ep->base.sk->sk_security; | ||
5180 | struct common_audit_data ad; | ||
5181 | struct lsm_network_audit net = {0,}; | ||
5182 | u8 peerlbl_active; | ||
5183 | u32 peer_sid = SECINITSID_UNLABELED; | ||
5184 | u32 conn_sid; | ||
5185 | int err = 0; | ||
5186 | |||
5187 | if (!selinux_policycap_extsockclass()) | ||
5188 | return 0; | ||
5189 | |||
5190 | peerlbl_active = selinux_peerlbl_enabled(); | ||
5191 | |||
5192 | if (peerlbl_active) { | ||
5193 | /* This will return peer_sid = SECSID_NULL if there are | ||
5194 | * no peer labels, see security_net_peersid_resolve(). | ||
5195 | */ | ||
5196 | err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, | ||
5197 | &peer_sid); | ||
5198 | if (err) | ||
5199 | return err; | ||
5200 | |||
5201 | if (peer_sid == SECSID_NULL) | ||
5202 | peer_sid = SECINITSID_UNLABELED; | ||
5203 | } | ||
5204 | |||
5205 | if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) { | ||
5206 | sksec->sctp_assoc_state = SCTP_ASSOC_SET; | ||
5207 | |||
5208 | /* Here as first association on socket. As the peer SID | ||
5209 | * was allowed by peer recv (and the netif/node checks), | ||
5210 | * then it is approved by policy and used as the primary | ||
5211 | * peer SID for getpeercon(3). | ||
5212 | */ | ||
5213 | sksec->peer_sid = peer_sid; | ||
5214 | } else if (sksec->peer_sid != peer_sid) { | ||
5215 | /* Other association peer SIDs are checked to enforce | ||
5216 | * consistency among the peer SIDs. | ||
5217 | */ | ||
5218 | ad.type = LSM_AUDIT_DATA_NET; | ||
5219 | ad.u.net = &net; | ||
5220 | ad.u.net->sk = ep->base.sk; | ||
5221 | err = avc_has_perm(&selinux_state, | ||
5222 | sksec->peer_sid, peer_sid, sksec->sclass, | ||
5223 | SCTP_SOCKET__ASSOCIATION, &ad); | ||
5224 | if (err) | ||
5225 | return err; | ||
5226 | } | ||
5227 | |||
5228 | /* Compute the MLS component for the connection and store | ||
5229 | * the information in ep. This will be used by SCTP TCP type | ||
5230 | * sockets and peeled off connections as they cause a new | ||
5231 | * socket to be generated. selinux_sctp_sk_clone() will then | ||
5232 | * plug this into the new socket. | ||
5233 | */ | ||
5234 | err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid); | ||
5235 | if (err) | ||
5236 | return err; | ||
5237 | |||
5238 | ep->secid = conn_sid; | ||
5239 | ep->peer_secid = peer_sid; | ||
5240 | |||
5241 | /* Set any NetLabel labels including CIPSO/CALIPSO options. */ | ||
5242 | return selinux_netlbl_sctp_assoc_request(ep, skb); | ||
5243 | } | ||
5244 | |||
5245 | /* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting | ||
5246 | * based on their @optname. | ||
5247 | */ | ||
5248 | static int selinux_sctp_bind_connect(struct sock *sk, int optname, | ||
5249 | struct sockaddr *address, | ||
5250 | int addrlen) | ||
5251 | { | ||
5252 | int len, err = 0, walk_size = 0; | ||
5253 | void *addr_buf; | ||
5254 | struct sockaddr *addr; | ||
5255 | struct socket *sock; | ||
5256 | |||
5257 | if (!selinux_policycap_extsockclass()) | ||
5258 | return 0; | ||
5259 | |||
5260 | /* Process one or more addresses that may be IPv4 or IPv6 */ | ||
5261 | sock = sk->sk_socket; | ||
5262 | addr_buf = address; | ||
5263 | |||
5264 | while (walk_size < addrlen) { | ||
5265 | addr = addr_buf; | ||
5266 | switch (addr->sa_family) { | ||
5267 | case AF_INET: | ||
5268 | len = sizeof(struct sockaddr_in); | ||
5269 | break; | ||
5270 | case AF_INET6: | ||
5271 | len = sizeof(struct sockaddr_in6); | ||
5272 | break; | ||
5273 | default: | ||
5274 | return -EAFNOSUPPORT; | ||
5275 | } | ||
5276 | |||
5277 | err = -EINVAL; | ||
5278 | switch (optname) { | ||
5279 | /* Bind checks */ | ||
5280 | case SCTP_PRIMARY_ADDR: | ||
5281 | case SCTP_SET_PEER_PRIMARY_ADDR: | ||
5282 | case SCTP_SOCKOPT_BINDX_ADD: | ||
5283 | err = selinux_socket_bind(sock, addr, len); | ||
5284 | break; | ||
5285 | /* Connect checks */ | ||
5286 | case SCTP_SOCKOPT_CONNECTX: | ||
5287 | case SCTP_PARAM_SET_PRIMARY: | ||
5288 | case SCTP_PARAM_ADD_IP: | ||
5289 | case SCTP_SENDMSG_CONNECT: | ||
5290 | err = selinux_socket_connect_helper(sock, addr, len); | ||
5291 | if (err) | ||
5292 | return err; | ||
5293 | |||
5294 | /* As selinux_sctp_bind_connect() is called by the | ||
5295 | * SCTP protocol layer, the socket is already locked, | ||
5296 | * therefore selinux_netlbl_socket_connect_locked() is | ||
5297 | * is called here. The situations handled are: | ||
5298 | * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2), | ||
5299 | * whenever a new IP address is added or when a new | ||
5300 | * primary address is selected. | ||
5301 | * Note that an SCTP connect(2) call happens before | ||
5302 | * the SCTP protocol layer and is handled via | ||
5303 | * selinux_socket_connect(). | ||
5304 | */ | ||
5305 | err = selinux_netlbl_socket_connect_locked(sk, addr); | ||
5306 | break; | ||
5307 | } | ||
5308 | |||
5309 | if (err) | ||
5310 | return err; | ||
5311 | |||
5312 | addr_buf += len; | ||
5313 | walk_size += len; | ||
5314 | } | ||
5315 | |||
5316 | return 0; | ||
5317 | } | ||
5318 | |||
5319 | /* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */ | ||
5320 | static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, | ||
5321 | struct sock *newsk) | ||
5322 | { | ||
5323 | struct sk_security_struct *sksec = sk->sk_security; | ||
5324 | struct sk_security_struct *newsksec = newsk->sk_security; | ||
5325 | |||
5326 | /* If policy does not support SECCLASS_SCTP_SOCKET then call | ||
5327 | * the non-sctp clone version. | ||
5328 | */ | ||
5329 | if (!selinux_policycap_extsockclass()) | ||
5330 | return selinux_sk_clone_security(sk, newsk); | ||
5331 | |||
5332 | newsksec->sid = ep->secid; | ||
5333 | newsksec->peer_sid = ep->peer_secid; | ||
5334 | newsksec->sclass = sksec->sclass; | ||
5335 | selinux_netlbl_sctp_sk_clone(sk, newsk); | ||
5336 | } | ||
5337 | |||
4946 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 5338 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
4947 | struct request_sock *req) | 5339 | struct request_sock *req) |
4948 | { | 5340 | { |
@@ -5001,7 +5393,9 @@ static int selinux_secmark_relabel_packet(u32 sid) | |||
5001 | __tsec = current_security(); | 5393 | __tsec = current_security(); |
5002 | tsid = __tsec->sid; | 5394 | tsid = __tsec->sid; |
5003 | 5395 | ||
5004 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); | 5396 | return avc_has_perm(&selinux_state, |
5397 | tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, | ||
5398 | NULL); | ||
5005 | } | 5399 | } |
5006 | 5400 | ||
5007 | static void selinux_secmark_refcount_inc(void) | 5401 | static void selinux_secmark_refcount_inc(void) |
@@ -5049,7 +5443,8 @@ static int selinux_tun_dev_create(void) | |||
5049 | * connections unlike traditional sockets - check the TUN driver to | 5443 | * connections unlike traditional sockets - check the TUN driver to |
5050 | * get a better understanding of why this socket is special */ | 5444 | * get a better understanding of why this socket is special */ |
5051 | 5445 | ||
5052 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | 5446 | return avc_has_perm(&selinux_state, |
5447 | sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
5053 | NULL); | 5448 | NULL); |
5054 | } | 5449 | } |
5055 | 5450 | ||
@@ -5057,7 +5452,8 @@ static int selinux_tun_dev_attach_queue(void *security) | |||
5057 | { | 5452 | { |
5058 | struct tun_security_struct *tunsec = security; | 5453 | struct tun_security_struct *tunsec = security; |
5059 | 5454 | ||
5060 | return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, | 5455 | return avc_has_perm(&selinux_state, |
5456 | current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, | ||
5061 | TUN_SOCKET__ATTACH_QUEUE, NULL); | 5457 | TUN_SOCKET__ATTACH_QUEUE, NULL); |
5062 | } | 5458 | } |
5063 | 5459 | ||
@@ -5085,11 +5481,13 @@ static int selinux_tun_dev_open(void *security) | |||
5085 | u32 sid = current_sid(); | 5481 | u32 sid = current_sid(); |
5086 | int err; | 5482 | int err; |
5087 | 5483 | ||
5088 | err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET, | 5484 | err = avc_has_perm(&selinux_state, |
5485 | sid, tunsec->sid, SECCLASS_TUN_SOCKET, | ||
5089 | TUN_SOCKET__RELABELFROM, NULL); | 5486 | TUN_SOCKET__RELABELFROM, NULL); |
5090 | if (err) | 5487 | if (err) |
5091 | return err; | 5488 | return err; |
5092 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | 5489 | err = avc_has_perm(&selinux_state, |
5490 | sid, sid, SECCLASS_TUN_SOCKET, | ||
5093 | TUN_SOCKET__RELABELTO, NULL); | 5491 | TUN_SOCKET__RELABELTO, NULL); |
5094 | if (err) | 5492 | if (err) |
5095 | return err; | 5493 | return err; |
@@ -5120,7 +5518,8 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
5120 | sk->sk_protocol, nlh->nlmsg_type, | 5518 | sk->sk_protocol, nlh->nlmsg_type, |
5121 | secclass_map[sksec->sclass - 1].name, | 5519 | secclass_map[sksec->sclass - 1].name, |
5122 | task_pid_nr(current), current->comm); | 5520 | task_pid_nr(current), current->comm); |
5123 | if (!selinux_enforcing || security_get_allow_unknown()) | 5521 | if (!enforcing_enabled(&selinux_state) || |
5522 | security_get_allow_unknown(&selinux_state)) | ||
5124 | err = 0; | 5523 | err = 0; |
5125 | } | 5524 | } |
5126 | 5525 | ||
@@ -5150,7 +5549,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, | |||
5150 | u8 netlbl_active; | 5549 | u8 netlbl_active; |
5151 | u8 peerlbl_active; | 5550 | u8 peerlbl_active; |
5152 | 5551 | ||
5153 | if (!selinux_policycap_netpeer) | 5552 | if (!selinux_policycap_netpeer()) |
5154 | return NF_ACCEPT; | 5553 | return NF_ACCEPT; |
5155 | 5554 | ||
5156 | secmark_active = selinux_secmark_enabled(); | 5555 | secmark_active = selinux_secmark_enabled(); |
@@ -5179,7 +5578,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, | |||
5179 | } | 5578 | } |
5180 | 5579 | ||
5181 | if (secmark_active) | 5580 | if (secmark_active) |
5182 | if (avc_has_perm(peer_sid, skb->secmark, | 5581 | if (avc_has_perm(&selinux_state, |
5582 | peer_sid, skb->secmark, | ||
5183 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) | 5583 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) |
5184 | return NF_DROP; | 5584 | return NF_DROP; |
5185 | 5585 | ||
@@ -5291,7 +5691,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
5291 | return NF_DROP; | 5691 | return NF_DROP; |
5292 | 5692 | ||
5293 | if (selinux_secmark_enabled()) | 5693 | if (selinux_secmark_enabled()) |
5294 | if (avc_has_perm(sksec->sid, skb->secmark, | 5694 | if (avc_has_perm(&selinux_state, |
5695 | sksec->sid, skb->secmark, | ||
5295 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 5696 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
5296 | return NF_DROP_ERR(-ECONNREFUSED); | 5697 | return NF_DROP_ERR(-ECONNREFUSED); |
5297 | 5698 | ||
@@ -5319,7 +5720,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, | |||
5319 | * to the selinux_ip_postroute_compat() function to deal with the | 5720 | * to the selinux_ip_postroute_compat() function to deal with the |
5320 | * special handling. We do this in an attempt to keep this function | 5721 | * special handling. We do this in an attempt to keep this function |
5321 | * as fast and as clean as possible. */ | 5722 | * as fast and as clean as possible. */ |
5322 | if (!selinux_policycap_netpeer) | 5723 | if (!selinux_policycap_netpeer()) |
5323 | return selinux_ip_postroute_compat(skb, ifindex, family); | 5724 | return selinux_ip_postroute_compat(skb, ifindex, family); |
5324 | 5725 | ||
5325 | secmark_active = selinux_secmark_enabled(); | 5726 | secmark_active = selinux_secmark_enabled(); |
@@ -5414,7 +5815,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, | |||
5414 | return NF_DROP; | 5815 | return NF_DROP; |
5415 | 5816 | ||
5416 | if (secmark_active) | 5817 | if (secmark_active) |
5417 | if (avc_has_perm(peer_sid, skb->secmark, | 5818 | if (avc_has_perm(&selinux_state, |
5819 | peer_sid, skb->secmark, | ||
5418 | SECCLASS_PACKET, secmark_perm, &ad)) | 5820 | SECCLASS_PACKET, secmark_perm, &ad)) |
5419 | return NF_DROP_ERR(-ECONNREFUSED); | 5821 | return NF_DROP_ERR(-ECONNREFUSED); |
5420 | 5822 | ||
@@ -5424,13 +5826,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, | |||
5424 | 5826 | ||
5425 | if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid)) | 5827 | if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid)) |
5426 | return NF_DROP; | 5828 | return NF_DROP; |
5427 | if (avc_has_perm(peer_sid, if_sid, | 5829 | if (avc_has_perm(&selinux_state, |
5830 | peer_sid, if_sid, | ||
5428 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 5831 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
5429 | return NF_DROP_ERR(-ECONNREFUSED); | 5832 | return NF_DROP_ERR(-ECONNREFUSED); |
5430 | 5833 | ||
5431 | if (sel_netnode_sid(addrp, family, &node_sid)) | 5834 | if (sel_netnode_sid(addrp, family, &node_sid)) |
5432 | return NF_DROP; | 5835 | return NF_DROP; |
5433 | if (avc_has_perm(peer_sid, node_sid, | 5836 | if (avc_has_perm(&selinux_state, |
5837 | peer_sid, node_sid, | ||
5434 | SECCLASS_NODE, NODE__SENDTO, &ad)) | 5838 | SECCLASS_NODE, NODE__SENDTO, &ad)) |
5435 | return NF_DROP_ERR(-ECONNREFUSED); | 5839 | return NF_DROP_ERR(-ECONNREFUSED); |
5436 | } | 5840 | } |
@@ -5518,7 +5922,8 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
5518 | ad.type = LSM_AUDIT_DATA_IPC; | 5922 | ad.type = LSM_AUDIT_DATA_IPC; |
5519 | ad.u.ipc_id = ipc_perms->key; | 5923 | ad.u.ipc_id = ipc_perms->key; |
5520 | 5924 | ||
5521 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 5925 | return avc_has_perm(&selinux_state, |
5926 | sid, isec->sid, isec->sclass, perms, &ad); | ||
5522 | } | 5927 | } |
5523 | 5928 | ||
5524 | static int selinux_msg_msg_alloc_security(struct msg_msg *msg) | 5929 | static int selinux_msg_msg_alloc_security(struct msg_msg *msg) |
@@ -5548,7 +5953,8 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) | |||
5548 | ad.type = LSM_AUDIT_DATA_IPC; | 5953 | ad.type = LSM_AUDIT_DATA_IPC; |
5549 | ad.u.ipc_id = msq->key; | 5954 | ad.u.ipc_id = msq->key; |
5550 | 5955 | ||
5551 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 5956 | rc = avc_has_perm(&selinux_state, |
5957 | sid, isec->sid, SECCLASS_MSGQ, | ||
5552 | MSGQ__CREATE, &ad); | 5958 | MSGQ__CREATE, &ad); |
5553 | if (rc) { | 5959 | if (rc) { |
5554 | ipc_free_security(msq); | 5960 | ipc_free_security(msq); |
@@ -5573,7 +5979,8 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | |||
5573 | ad.type = LSM_AUDIT_DATA_IPC; | 5979 | ad.type = LSM_AUDIT_DATA_IPC; |
5574 | ad.u.ipc_id = msq->key; | 5980 | ad.u.ipc_id = msq->key; |
5575 | 5981 | ||
5576 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 5982 | return avc_has_perm(&selinux_state, |
5983 | sid, isec->sid, SECCLASS_MSGQ, | ||
5577 | MSGQ__ASSOCIATE, &ad); | 5984 | MSGQ__ASSOCIATE, &ad); |
5578 | } | 5985 | } |
5579 | 5986 | ||
@@ -5586,7 +5993,8 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) | |||
5586 | case IPC_INFO: | 5993 | case IPC_INFO: |
5587 | case MSG_INFO: | 5994 | case MSG_INFO: |
5588 | /* No specific object, just general system-wide information. */ | 5995 | /* No specific object, just general system-wide information. */ |
5589 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 5996 | return avc_has_perm(&selinux_state, |
5997 | current_sid(), SECINITSID_KERNEL, | ||
5590 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | 5998 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); |
5591 | case IPC_STAT: | 5999 | case IPC_STAT: |
5592 | case MSG_STAT: | 6000 | case MSG_STAT: |
@@ -5625,8 +6033,8 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m | |||
5625 | * Compute new sid based on current process and | 6033 | * Compute new sid based on current process and |
5626 | * message queue this message will be stored in | 6034 | * message queue this message will be stored in |
5627 | */ | 6035 | */ |
5628 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, | 6036 | rc = security_transition_sid(&selinux_state, sid, isec->sid, |
5629 | NULL, &msec->sid); | 6037 | SECCLASS_MSG, NULL, &msec->sid); |
5630 | if (rc) | 6038 | if (rc) |
5631 | return rc; | 6039 | return rc; |
5632 | } | 6040 | } |
@@ -5635,15 +6043,18 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m | |||
5635 | ad.u.ipc_id = msq->key; | 6043 | ad.u.ipc_id = msq->key; |
5636 | 6044 | ||
5637 | /* Can this process write to the queue? */ | 6045 | /* Can this process write to the queue? */ |
5638 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 6046 | rc = avc_has_perm(&selinux_state, |
6047 | sid, isec->sid, SECCLASS_MSGQ, | ||
5639 | MSGQ__WRITE, &ad); | 6048 | MSGQ__WRITE, &ad); |
5640 | if (!rc) | 6049 | if (!rc) |
5641 | /* Can this process send the message */ | 6050 | /* Can this process send the message */ |
5642 | rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG, | 6051 | rc = avc_has_perm(&selinux_state, |
6052 | sid, msec->sid, SECCLASS_MSG, | ||
5643 | MSG__SEND, &ad); | 6053 | MSG__SEND, &ad); |
5644 | if (!rc) | 6054 | if (!rc) |
5645 | /* Can the message be put in the queue? */ | 6055 | /* Can the message be put in the queue? */ |
5646 | rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ, | 6056 | rc = avc_has_perm(&selinux_state, |
6057 | msec->sid, isec->sid, SECCLASS_MSGQ, | ||
5647 | MSGQ__ENQUEUE, &ad); | 6058 | MSGQ__ENQUEUE, &ad); |
5648 | 6059 | ||
5649 | return rc; | 6060 | return rc; |
@@ -5665,10 +6076,12 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m | |||
5665 | ad.type = LSM_AUDIT_DATA_IPC; | 6076 | ad.type = LSM_AUDIT_DATA_IPC; |
5666 | ad.u.ipc_id = msq->key; | 6077 | ad.u.ipc_id = msq->key; |
5667 | 6078 | ||
5668 | rc = avc_has_perm(sid, isec->sid, | 6079 | rc = avc_has_perm(&selinux_state, |
6080 | sid, isec->sid, | ||
5669 | SECCLASS_MSGQ, MSGQ__READ, &ad); | 6081 | SECCLASS_MSGQ, MSGQ__READ, &ad); |
5670 | if (!rc) | 6082 | if (!rc) |
5671 | rc = avc_has_perm(sid, msec->sid, | 6083 | rc = avc_has_perm(&selinux_state, |
6084 | sid, msec->sid, | ||
5672 | SECCLASS_MSG, MSG__RECEIVE, &ad); | 6085 | SECCLASS_MSG, MSG__RECEIVE, &ad); |
5673 | return rc; | 6086 | return rc; |
5674 | } | 6087 | } |
@@ -5690,7 +6103,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) | |||
5690 | ad.type = LSM_AUDIT_DATA_IPC; | 6103 | ad.type = LSM_AUDIT_DATA_IPC; |
5691 | ad.u.ipc_id = shp->key; | 6104 | ad.u.ipc_id = shp->key; |
5692 | 6105 | ||
5693 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 6106 | rc = avc_has_perm(&selinux_state, |
6107 | sid, isec->sid, SECCLASS_SHM, | ||
5694 | SHM__CREATE, &ad); | 6108 | SHM__CREATE, &ad); |
5695 | if (rc) { | 6109 | if (rc) { |
5696 | ipc_free_security(shp); | 6110 | ipc_free_security(shp); |
@@ -5715,7 +6129,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) | |||
5715 | ad.type = LSM_AUDIT_DATA_IPC; | 6129 | ad.type = LSM_AUDIT_DATA_IPC; |
5716 | ad.u.ipc_id = shp->key; | 6130 | ad.u.ipc_id = shp->key; |
5717 | 6131 | ||
5718 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 6132 | return avc_has_perm(&selinux_state, |
6133 | sid, isec->sid, SECCLASS_SHM, | ||
5719 | SHM__ASSOCIATE, &ad); | 6134 | SHM__ASSOCIATE, &ad); |
5720 | } | 6135 | } |
5721 | 6136 | ||
@@ -5729,7 +6144,8 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) | |||
5729 | case IPC_INFO: | 6144 | case IPC_INFO: |
5730 | case SHM_INFO: | 6145 | case SHM_INFO: |
5731 | /* No specific object, just general system-wide information. */ | 6146 | /* No specific object, just general system-wide information. */ |
5732 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 6147 | return avc_has_perm(&selinux_state, |
6148 | current_sid(), SECINITSID_KERNEL, | ||
5733 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | 6149 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); |
5734 | case IPC_STAT: | 6150 | case IPC_STAT: |
5735 | case SHM_STAT: | 6151 | case SHM_STAT: |
@@ -5783,7 +6199,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) | |||
5783 | ad.type = LSM_AUDIT_DATA_IPC; | 6199 | ad.type = LSM_AUDIT_DATA_IPC; |
5784 | ad.u.ipc_id = sma->key; | 6200 | ad.u.ipc_id = sma->key; |
5785 | 6201 | ||
5786 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 6202 | rc = avc_has_perm(&selinux_state, |
6203 | sid, isec->sid, SECCLASS_SEM, | ||
5787 | SEM__CREATE, &ad); | 6204 | SEM__CREATE, &ad); |
5788 | if (rc) { | 6205 | if (rc) { |
5789 | ipc_free_security(sma); | 6206 | ipc_free_security(sma); |
@@ -5808,7 +6225,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) | |||
5808 | ad.type = LSM_AUDIT_DATA_IPC; | 6225 | ad.type = LSM_AUDIT_DATA_IPC; |
5809 | ad.u.ipc_id = sma->key; | 6226 | ad.u.ipc_id = sma->key; |
5810 | 6227 | ||
5811 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 6228 | return avc_has_perm(&selinux_state, |
6229 | sid, isec->sid, SECCLASS_SEM, | ||
5812 | SEM__ASSOCIATE, &ad); | 6230 | SEM__ASSOCIATE, &ad); |
5813 | } | 6231 | } |
5814 | 6232 | ||
@@ -5822,7 +6240,8 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) | |||
5822 | case IPC_INFO: | 6240 | case IPC_INFO: |
5823 | case SEM_INFO: | 6241 | case SEM_INFO: |
5824 | /* No specific object, just general system-wide information. */ | 6242 | /* No specific object, just general system-wide information. */ |
5825 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | 6243 | return avc_has_perm(&selinux_state, |
6244 | current_sid(), SECINITSID_KERNEL, | ||
5826 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | 6245 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); |
5827 | case GETPID: | 6246 | case GETPID: |
5828 | case GETNCNT: | 6247 | case GETNCNT: |
@@ -5908,7 +6327,8 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5908 | __tsec = __task_cred(p)->security; | 6327 | __tsec = __task_cred(p)->security; |
5909 | 6328 | ||
5910 | if (current != p) { | 6329 | if (current != p) { |
5911 | error = avc_has_perm(current_sid(), __tsec->sid, | 6330 | error = avc_has_perm(&selinux_state, |
6331 | current_sid(), __tsec->sid, | ||
5912 | SECCLASS_PROCESS, PROCESS__GETATTR, NULL); | 6332 | SECCLASS_PROCESS, PROCESS__GETATTR, NULL); |
5913 | if (error) | 6333 | if (error) |
5914 | goto bad; | 6334 | goto bad; |
@@ -5935,7 +6355,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5935 | if (!sid) | 6355 | if (!sid) |
5936 | return 0; | 6356 | return 0; |
5937 | 6357 | ||
5938 | error = security_sid_to_context(sid, value, &len); | 6358 | error = security_sid_to_context(&selinux_state, sid, value, &len); |
5939 | if (error) | 6359 | if (error) |
5940 | return error; | 6360 | return error; |
5941 | return len; | 6361 | return len; |
@@ -5957,19 +6377,24 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
5957 | * Basic control over ability to set these attributes at all. | 6377 | * Basic control over ability to set these attributes at all. |
5958 | */ | 6378 | */ |
5959 | if (!strcmp(name, "exec")) | 6379 | if (!strcmp(name, "exec")) |
5960 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, | 6380 | error = avc_has_perm(&selinux_state, |
6381 | mysid, mysid, SECCLASS_PROCESS, | ||
5961 | PROCESS__SETEXEC, NULL); | 6382 | PROCESS__SETEXEC, NULL); |
5962 | else if (!strcmp(name, "fscreate")) | 6383 | else if (!strcmp(name, "fscreate")) |
5963 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, | 6384 | error = avc_has_perm(&selinux_state, |
6385 | mysid, mysid, SECCLASS_PROCESS, | ||
5964 | PROCESS__SETFSCREATE, NULL); | 6386 | PROCESS__SETFSCREATE, NULL); |
5965 | else if (!strcmp(name, "keycreate")) | 6387 | else if (!strcmp(name, "keycreate")) |
5966 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, | 6388 | error = avc_has_perm(&selinux_state, |
6389 | mysid, mysid, SECCLASS_PROCESS, | ||
5967 | PROCESS__SETKEYCREATE, NULL); | 6390 | PROCESS__SETKEYCREATE, NULL); |
5968 | else if (!strcmp(name, "sockcreate")) | 6391 | else if (!strcmp(name, "sockcreate")) |
5969 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, | 6392 | error = avc_has_perm(&selinux_state, |
6393 | mysid, mysid, SECCLASS_PROCESS, | ||
5970 | PROCESS__SETSOCKCREATE, NULL); | 6394 | PROCESS__SETSOCKCREATE, NULL); |
5971 | else if (!strcmp(name, "current")) | 6395 | else if (!strcmp(name, "current")) |
5972 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, | 6396 | error = avc_has_perm(&selinux_state, |
6397 | mysid, mysid, SECCLASS_PROCESS, | ||
5973 | PROCESS__SETCURRENT, NULL); | 6398 | PROCESS__SETCURRENT, NULL); |
5974 | else | 6399 | else |
5975 | error = -EINVAL; | 6400 | error = -EINVAL; |
@@ -5982,7 +6407,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
5982 | str[size-1] = 0; | 6407 | str[size-1] = 0; |
5983 | size--; | 6408 | size--; |
5984 | } | 6409 | } |
5985 | error = security_context_to_sid(value, size, &sid, GFP_KERNEL); | 6410 | error = security_context_to_sid(&selinux_state, value, size, |
6411 | &sid, GFP_KERNEL); | ||
5986 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 6412 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5987 | if (!has_cap_mac_admin(true)) { | 6413 | if (!has_cap_mac_admin(true)) { |
5988 | struct audit_buffer *ab; | 6414 | struct audit_buffer *ab; |
@@ -6001,8 +6427,9 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
6001 | 6427 | ||
6002 | return error; | 6428 | return error; |
6003 | } | 6429 | } |
6004 | error = security_context_to_sid_force(value, size, | 6430 | error = security_context_to_sid_force( |
6005 | &sid); | 6431 | &selinux_state, |
6432 | value, size, &sid); | ||
6006 | } | 6433 | } |
6007 | if (error) | 6434 | if (error) |
6008 | return error; | 6435 | return error; |
@@ -6024,7 +6451,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
6024 | } else if (!strcmp(name, "fscreate")) { | 6451 | } else if (!strcmp(name, "fscreate")) { |
6025 | tsec->create_sid = sid; | 6452 | tsec->create_sid = sid; |
6026 | } else if (!strcmp(name, "keycreate")) { | 6453 | } else if (!strcmp(name, "keycreate")) { |
6027 | error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE, | 6454 | error = avc_has_perm(&selinux_state, |
6455 | mysid, sid, SECCLASS_KEY, KEY__CREATE, | ||
6028 | NULL); | 6456 | NULL); |
6029 | if (error) | 6457 | if (error) |
6030 | goto abort_change; | 6458 | goto abort_change; |
@@ -6039,13 +6467,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
6039 | /* Only allow single threaded processes to change context */ | 6467 | /* Only allow single threaded processes to change context */ |
6040 | error = -EPERM; | 6468 | error = -EPERM; |
6041 | if (!current_is_single_threaded()) { | 6469 | if (!current_is_single_threaded()) { |
6042 | error = security_bounded_transition(tsec->sid, sid); | 6470 | error = security_bounded_transition(&selinux_state, |
6471 | tsec->sid, sid); | ||
6043 | if (error) | 6472 | if (error) |
6044 | goto abort_change; | 6473 | goto abort_change; |
6045 | } | 6474 | } |
6046 | 6475 | ||
6047 | /* Check permissions for the transition. */ | 6476 | /* Check permissions for the transition. */ |
6048 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 6477 | error = avc_has_perm(&selinux_state, |
6478 | tsec->sid, sid, SECCLASS_PROCESS, | ||
6049 | PROCESS__DYNTRANSITION, NULL); | 6479 | PROCESS__DYNTRANSITION, NULL); |
6050 | if (error) | 6480 | if (error) |
6051 | goto abort_change; | 6481 | goto abort_change; |
@@ -6054,7 +6484,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
6054 | Otherwise, leave SID unchanged and fail. */ | 6484 | Otherwise, leave SID unchanged and fail. */ |
6055 | ptsid = ptrace_parent_sid(); | 6485 | ptsid = ptrace_parent_sid(); |
6056 | if (ptsid != 0) { | 6486 | if (ptsid != 0) { |
6057 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 6487 | error = avc_has_perm(&selinux_state, |
6488 | ptsid, sid, SECCLASS_PROCESS, | ||
6058 | PROCESS__PTRACE, NULL); | 6489 | PROCESS__PTRACE, NULL); |
6059 | if (error) | 6490 | if (error) |
6060 | goto abort_change; | 6491 | goto abort_change; |
@@ -6081,12 +6512,14 @@ static int selinux_ismaclabel(const char *name) | |||
6081 | 6512 | ||
6082 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 6513 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
6083 | { | 6514 | { |
6084 | return security_sid_to_context(secid, secdata, seclen); | 6515 | return security_sid_to_context(&selinux_state, secid, |
6516 | secdata, seclen); | ||
6085 | } | 6517 | } |
6086 | 6518 | ||
6087 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 6519 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
6088 | { | 6520 | { |
6089 | return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL); | 6521 | return security_context_to_sid(&selinux_state, secdata, seclen, |
6522 | secid, GFP_KERNEL); | ||
6090 | } | 6523 | } |
6091 | 6524 | ||
6092 | static void selinux_release_secctx(char *secdata, u32 seclen) | 6525 | static void selinux_release_secctx(char *secdata, u32 seclen) |
@@ -6178,7 +6611,8 @@ static int selinux_key_permission(key_ref_t key_ref, | |||
6178 | key = key_ref_to_ptr(key_ref); | 6611 | key = key_ref_to_ptr(key_ref); |
6179 | ksec = key->security; | 6612 | ksec = key->security; |
6180 | 6613 | ||
6181 | return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); | 6614 | return avc_has_perm(&selinux_state, |
6615 | sid, ksec->sid, SECCLASS_KEY, perm, NULL); | ||
6182 | } | 6616 | } |
6183 | 6617 | ||
6184 | static int selinux_key_getsecurity(struct key *key, char **_buffer) | 6618 | static int selinux_key_getsecurity(struct key *key, char **_buffer) |
@@ -6188,7 +6622,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
6188 | unsigned len; | 6622 | unsigned len; |
6189 | int rc; | 6623 | int rc; |
6190 | 6624 | ||
6191 | rc = security_sid_to_context(ksec->sid, &context, &len); | 6625 | rc = security_sid_to_context(&selinux_state, ksec->sid, |
6626 | &context, &len); | ||
6192 | if (!rc) | 6627 | if (!rc) |
6193 | rc = len; | 6628 | rc = len; |
6194 | *_buffer = context; | 6629 | *_buffer = context; |
@@ -6213,7 +6648,8 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val) | |||
6213 | ibpkey.subnet_prefix = subnet_prefix; | 6648 | ibpkey.subnet_prefix = subnet_prefix; |
6214 | ibpkey.pkey = pkey_val; | 6649 | ibpkey.pkey = pkey_val; |
6215 | ad.u.ibpkey = &ibpkey; | 6650 | ad.u.ibpkey = &ibpkey; |
6216 | return avc_has_perm(sec->sid, sid, | 6651 | return avc_has_perm(&selinux_state, |
6652 | sec->sid, sid, | ||
6217 | SECCLASS_INFINIBAND_PKEY, | 6653 | SECCLASS_INFINIBAND_PKEY, |
6218 | INFINIBAND_PKEY__ACCESS, &ad); | 6654 | INFINIBAND_PKEY__ACCESS, &ad); |
6219 | } | 6655 | } |
@@ -6227,7 +6663,8 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, | |||
6227 | struct ib_security_struct *sec = ib_sec; | 6663 | struct ib_security_struct *sec = ib_sec; |
6228 | struct lsm_ibendport_audit ibendport; | 6664 | struct lsm_ibendport_audit ibendport; |
6229 | 6665 | ||
6230 | err = security_ib_endport_sid(dev_name, port_num, &sid); | 6666 | err = security_ib_endport_sid(&selinux_state, dev_name, port_num, |
6667 | &sid); | ||
6231 | 6668 | ||
6232 | if (err) | 6669 | if (err) |
6233 | return err; | 6670 | return err; |
@@ -6236,7 +6673,8 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, | |||
6236 | strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name)); | 6673 | strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name)); |
6237 | ibendport.port = port_num; | 6674 | ibendport.port = port_num; |
6238 | ad.u.ibendport = &ibendport; | 6675 | ad.u.ibendport = &ibendport; |
6239 | return avc_has_perm(sec->sid, sid, | 6676 | return avc_has_perm(&selinux_state, |
6677 | sec->sid, sid, | ||
6240 | SECCLASS_INFINIBAND_ENDPORT, | 6678 | SECCLASS_INFINIBAND_ENDPORT, |
6241 | INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); | 6679 | INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); |
6242 | } | 6680 | } |
@@ -6269,11 +6707,13 @@ static int selinux_bpf(int cmd, union bpf_attr *attr, | |||
6269 | 6707 | ||
6270 | switch (cmd) { | 6708 | switch (cmd) { |
6271 | case BPF_MAP_CREATE: | 6709 | case BPF_MAP_CREATE: |
6272 | ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, | 6710 | ret = avc_has_perm(&selinux_state, |
6711 | sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, | ||
6273 | NULL); | 6712 | NULL); |
6274 | break; | 6713 | break; |
6275 | case BPF_PROG_LOAD: | 6714 | case BPF_PROG_LOAD: |
6276 | ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, | 6715 | ret = avc_has_perm(&selinux_state, |
6716 | sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, | ||
6277 | NULL); | 6717 | NULL); |
6278 | break; | 6718 | break; |
6279 | default: | 6719 | default: |
@@ -6313,14 +6753,16 @@ static int bpf_fd_pass(struct file *file, u32 sid) | |||
6313 | if (file->f_op == &bpf_map_fops) { | 6753 | if (file->f_op == &bpf_map_fops) { |
6314 | map = file->private_data; | 6754 | map = file->private_data; |
6315 | bpfsec = map->security; | 6755 | bpfsec = map->security; |
6316 | ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | 6756 | ret = avc_has_perm(&selinux_state, |
6757 | sid, bpfsec->sid, SECCLASS_BPF, | ||
6317 | bpf_map_fmode_to_av(file->f_mode), NULL); | 6758 | bpf_map_fmode_to_av(file->f_mode), NULL); |
6318 | if (ret) | 6759 | if (ret) |
6319 | return ret; | 6760 | return ret; |
6320 | } else if (file->f_op == &bpf_prog_fops) { | 6761 | } else if (file->f_op == &bpf_prog_fops) { |
6321 | prog = file->private_data; | 6762 | prog = file->private_data; |
6322 | bpfsec = prog->aux->security; | 6763 | bpfsec = prog->aux->security; |
6323 | ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | 6764 | ret = avc_has_perm(&selinux_state, |
6765 | sid, bpfsec->sid, SECCLASS_BPF, | ||
6324 | BPF__PROG_RUN, NULL); | 6766 | BPF__PROG_RUN, NULL); |
6325 | if (ret) | 6767 | if (ret) |
6326 | return ret; | 6768 | return ret; |
@@ -6334,7 +6776,8 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) | |||
6334 | struct bpf_security_struct *bpfsec; | 6776 | struct bpf_security_struct *bpfsec; |
6335 | 6777 | ||
6336 | bpfsec = map->security; | 6778 | bpfsec = map->security; |
6337 | return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | 6779 | return avc_has_perm(&selinux_state, |
6780 | sid, bpfsec->sid, SECCLASS_BPF, | ||
6338 | bpf_map_fmode_to_av(fmode), NULL); | 6781 | bpf_map_fmode_to_av(fmode), NULL); |
6339 | } | 6782 | } |
6340 | 6783 | ||
@@ -6344,7 +6787,8 @@ static int selinux_bpf_prog(struct bpf_prog *prog) | |||
6344 | struct bpf_security_struct *bpfsec; | 6787 | struct bpf_security_struct *bpfsec; |
6345 | 6788 | ||
6346 | bpfsec = prog->aux->security; | 6789 | bpfsec = prog->aux->security; |
6347 | return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | 6790 | return avc_has_perm(&selinux_state, |
6791 | sid, bpfsec->sid, SECCLASS_BPF, | ||
6348 | BPF__PROG_RUN, NULL); | 6792 | BPF__PROG_RUN, NULL); |
6349 | } | 6793 | } |
6350 | 6794 | ||
@@ -6563,6 +7007,9 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
6563 | LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), | 7007 | LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), |
6564 | LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), | 7008 | LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), |
6565 | LSM_HOOK_INIT(sock_graft, selinux_sock_graft), | 7009 | LSM_HOOK_INIT(sock_graft, selinux_sock_graft), |
7010 | LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request), | ||
7011 | LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), | ||
7012 | LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect), | ||
6566 | LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), | 7013 | LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), |
6567 | LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), | 7014 | LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), |
6568 | LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), | 7015 | LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), |
@@ -6638,6 +7085,12 @@ static __init int selinux_init(void) | |||
6638 | 7085 | ||
6639 | printk(KERN_INFO "SELinux: Initializing.\n"); | 7086 | printk(KERN_INFO "SELinux: Initializing.\n"); |
6640 | 7087 | ||
7088 | memset(&selinux_state, 0, sizeof(selinux_state)); | ||
7089 | enforcing_set(&selinux_state, selinux_enforcing_boot); | ||
7090 | selinux_state.checkreqprot = selinux_checkreqprot_boot; | ||
7091 | selinux_ss_init(&selinux_state.ss); | ||
7092 | selinux_avc_init(&selinux_state.avc); | ||
7093 | |||
6641 | /* Set the security state for the initial task. */ | 7094 | /* Set the security state for the initial task. */ |
6642 | cred_init_security(); | 7095 | cred_init_security(); |
6643 | 7096 | ||
@@ -6651,6 +7104,12 @@ static __init int selinux_init(void) | |||
6651 | 0, SLAB_PANIC, NULL); | 7104 | 0, SLAB_PANIC, NULL); |
6652 | avc_init(); | 7105 | avc_init(); |
6653 | 7106 | ||
7107 | avtab_cache_init(); | ||
7108 | |||
7109 | ebitmap_cache_init(); | ||
7110 | |||
7111 | hashtab_cache_init(); | ||
7112 | |||
6654 | security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); | 7113 | security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); |
6655 | 7114 | ||
6656 | if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) | 7115 | if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) |
@@ -6659,7 +7118,7 @@ static __init int selinux_init(void) | |||
6659 | if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET)) | 7118 | if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET)) |
6660 | panic("SELinux: Unable to register AVC LSM notifier callback\n"); | 7119 | panic("SELinux: Unable to register AVC LSM notifier callback\n"); |
6661 | 7120 | ||
6662 | if (selinux_enforcing) | 7121 | if (selinux_enforcing_boot) |
6663 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); | 7122 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); |
6664 | else | 7123 | else |
6665 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); | 7124 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); |
@@ -6780,23 +7239,22 @@ static void selinux_nf_ip_exit(void) | |||
6780 | #endif /* CONFIG_NETFILTER */ | 7239 | #endif /* CONFIG_NETFILTER */ |
6781 | 7240 | ||
6782 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 7241 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
6783 | static int selinux_disabled; | 7242 | int selinux_disable(struct selinux_state *state) |
6784 | |||
6785 | int selinux_disable(void) | ||
6786 | { | 7243 | { |
6787 | if (ss_initialized) { | 7244 | if (state->initialized) { |
6788 | /* Not permitted after initial policy load. */ | 7245 | /* Not permitted after initial policy load. */ |
6789 | return -EINVAL; | 7246 | return -EINVAL; |
6790 | } | 7247 | } |
6791 | 7248 | ||
6792 | if (selinux_disabled) { | 7249 | if (state->disabled) { |
6793 | /* Only do this once. */ | 7250 | /* Only do this once. */ |
6794 | return -EINVAL; | 7251 | return -EINVAL; |
6795 | } | 7252 | } |
6796 | 7253 | ||
7254 | state->disabled = 1; | ||
7255 | |||
6797 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); | 7256 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); |
6798 | 7257 | ||
6799 | selinux_disabled = 1; | ||
6800 | selinux_enabled = 0; | 7258 | selinux_enabled = 0; |
6801 | 7259 | ||
6802 | security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); | 7260 | security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); |
diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c index e3614ee5f1c0..0a4b89d48297 100644 --- a/security/selinux/ibpkey.c +++ b/security/selinux/ibpkey.c | |||
@@ -152,7 +152,8 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid) | |||
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | ret = security_ib_pkey_sid(subnet_prefix, pkey_num, sid); | 155 | ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num, |
156 | sid); | ||
156 | if (ret) | 157 | if (ret) |
157 | goto out; | 158 | goto out; |
158 | 159 | ||
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 57d61cf36500..ef899bcfd2cb 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -20,12 +20,6 @@ | |||
20 | #include "av_permissions.h" | 20 | #include "av_permissions.h" |
21 | #include "security.h" | 21 | #include "security.h" |
22 | 22 | ||
23 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | ||
24 | extern int selinux_enforcing; | ||
25 | #else | ||
26 | #define selinux_enforcing 1 | ||
27 | #endif | ||
28 | |||
29 | /* | 23 | /* |
30 | * An entry in the AVC. | 24 | * An entry in the AVC. |
31 | */ | 25 | */ |
@@ -58,6 +52,7 @@ struct selinux_audit_data { | |||
58 | u32 audited; | 52 | u32 audited; |
59 | u32 denied; | 53 | u32 denied; |
60 | int result; | 54 | int result; |
55 | struct selinux_state *state; | ||
61 | }; | 56 | }; |
62 | 57 | ||
63 | /* | 58 | /* |
@@ -102,7 +97,8 @@ static inline u32 avc_audit_required(u32 requested, | |||
102 | return audited; | 97 | return audited; |
103 | } | 98 | } |
104 | 99 | ||
105 | int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | 100 | int slow_avc_audit(struct selinux_state *state, |
101 | u32 ssid, u32 tsid, u16 tclass, | ||
106 | u32 requested, u32 audited, u32 denied, int result, | 102 | u32 requested, u32 audited, u32 denied, int result, |
107 | struct common_audit_data *a, | 103 | struct common_audit_data *a, |
108 | unsigned flags); | 104 | unsigned flags); |
@@ -127,7 +123,8 @@ int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | |||
127 | * be performed under a lock, to allow the lock to be released | 123 | * be performed under a lock, to allow the lock to be released |
128 | * before calling the auditing code. | 124 | * before calling the auditing code. |
129 | */ | 125 | */ |
130 | static inline int avc_audit(u32 ssid, u32 tsid, | 126 | static inline int avc_audit(struct selinux_state *state, |
127 | u32 ssid, u32 tsid, | ||
131 | u16 tclass, u32 requested, | 128 | u16 tclass, u32 requested, |
132 | struct av_decision *avd, | 129 | struct av_decision *avd, |
133 | int result, | 130 | int result, |
@@ -138,31 +135,35 @@ static inline int avc_audit(u32 ssid, u32 tsid, | |||
138 | audited = avc_audit_required(requested, avd, result, 0, &denied); | 135 | audited = avc_audit_required(requested, avd, result, 0, &denied); |
139 | if (likely(!audited)) | 136 | if (likely(!audited)) |
140 | return 0; | 137 | return 0; |
141 | return slow_avc_audit(ssid, tsid, tclass, | 138 | return slow_avc_audit(state, ssid, tsid, tclass, |
142 | requested, audited, denied, result, | 139 | requested, audited, denied, result, |
143 | a, flags); | 140 | a, flags); |
144 | } | 141 | } |
145 | 142 | ||
146 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 143 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
147 | #define AVC_EXTENDED_PERMS 2 /* update extended permissions */ | 144 | #define AVC_EXTENDED_PERMS 2 /* update extended permissions */ |
148 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 145 | int avc_has_perm_noaudit(struct selinux_state *state, |
146 | u32 ssid, u32 tsid, | ||
149 | u16 tclass, u32 requested, | 147 | u16 tclass, u32 requested, |
150 | unsigned flags, | 148 | unsigned flags, |
151 | struct av_decision *avd); | 149 | struct av_decision *avd); |
152 | 150 | ||
153 | int avc_has_perm(u32 ssid, u32 tsid, | 151 | int avc_has_perm(struct selinux_state *state, |
152 | u32 ssid, u32 tsid, | ||
154 | u16 tclass, u32 requested, | 153 | u16 tclass, u32 requested, |
155 | struct common_audit_data *auditdata); | 154 | struct common_audit_data *auditdata); |
156 | int avc_has_perm_flags(u32 ssid, u32 tsid, | 155 | int avc_has_perm_flags(struct selinux_state *state, |
156 | u32 ssid, u32 tsid, | ||
157 | u16 tclass, u32 requested, | 157 | u16 tclass, u32 requested, |
158 | struct common_audit_data *auditdata, | 158 | struct common_audit_data *auditdata, |
159 | int flags); | 159 | int flags); |
160 | 160 | ||
161 | int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, | 161 | int avc_has_extended_perms(struct selinux_state *state, |
162 | u8 driver, u8 perm, struct common_audit_data *ad); | 162 | u32 ssid, u32 tsid, u16 tclass, u32 requested, |
163 | u8 driver, u8 perm, struct common_audit_data *ad); | ||
163 | 164 | ||
164 | 165 | ||
165 | u32 avc_policy_seqno(void); | 166 | u32 avc_policy_seqno(struct selinux_state *state); |
166 | 167 | ||
167 | #define AVC_CALLBACK_GRANT 1 | 168 | #define AVC_CALLBACK_GRANT 1 |
168 | #define AVC_CALLBACK_TRY_REVOKE 2 | 169 | #define AVC_CALLBACK_TRY_REVOKE 2 |
@@ -177,8 +178,11 @@ u32 avc_policy_seqno(void); | |||
177 | int avc_add_callback(int (*callback)(u32 event), u32 events); | 178 | int avc_add_callback(int (*callback)(u32 event), u32 events); |
178 | 179 | ||
179 | /* Exported to selinuxfs */ | 180 | /* Exported to selinuxfs */ |
180 | int avc_get_hash_stats(char *page); | 181 | struct selinux_avc; |
181 | extern unsigned int avc_cache_threshold; | 182 | int avc_get_hash_stats(struct selinux_avc *avc, char *page); |
183 | unsigned int avc_get_cache_threshold(struct selinux_avc *avc); | ||
184 | void avc_set_cache_threshold(struct selinux_avc *avc, | ||
185 | unsigned int cache_threshold); | ||
182 | 186 | ||
183 | /* Attempt to free avc node cache */ | 187 | /* Attempt to free avc node cache */ |
184 | void avc_disable(void); | 188 | void avc_disable(void); |
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 3bcc72769b87..88c384c5c09e 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h | |||
@@ -9,7 +9,8 @@ | |||
9 | 9 | ||
10 | #include "flask.h" | 10 | #include "flask.h" |
11 | 11 | ||
12 | int avc_ss_reset(u32 seqno); | 12 | struct selinux_avc; |
13 | int avc_ss_reset(struct selinux_avc *avc, u32 seqno); | ||
13 | 14 | ||
14 | /* Class/perm mapping support */ | 15 | /* Class/perm mapping support */ |
15 | struct security_class_mapping { | 16 | struct security_class_mapping { |
@@ -19,11 +20,5 @@ struct security_class_mapping { | |||
19 | 20 | ||
20 | extern struct security_class_mapping secclass_map[]; | 21 | extern struct security_class_mapping secclass_map[]; |
21 | 22 | ||
22 | /* | ||
23 | * The security server must be initialized before | ||
24 | * any labeling or access decisions can be provided. | ||
25 | */ | ||
26 | extern int ss_initialized; | ||
27 | |||
28 | #endif /* _SELINUX_AVC_SS_H_ */ | 23 | #endif /* _SELINUX_AVC_SS_H_ */ |
29 | 24 | ||
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index acdee7795297..7f0372426494 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
@@ -176,7 +176,7 @@ struct security_class_mapping secclass_map[] = { | |||
176 | { COMMON_CAP2_PERMS, NULL } }, | 176 | { COMMON_CAP2_PERMS, NULL } }, |
177 | { "sctp_socket", | 177 | { "sctp_socket", |
178 | { COMMON_SOCK_PERMS, | 178 | { COMMON_SOCK_PERMS, |
179 | "node_bind", NULL } }, | 179 | "node_bind", "name_connect", "association", NULL } }, |
180 | { "icmp_socket", | 180 | { "icmp_socket", |
181 | { COMMON_SOCK_PERMS, | 181 | { COMMON_SOCK_PERMS, |
182 | "node_bind", NULL } }, | 182 | "node_bind", NULL } }, |
diff --git a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h index ff4fddca9050..0e30eca02c48 100644 --- a/security/selinux/include/conditional.h +++ b/security/selinux/include/conditional.h | |||
@@ -13,10 +13,15 @@ | |||
13 | #ifndef _SELINUX_CONDITIONAL_H_ | 13 | #ifndef _SELINUX_CONDITIONAL_H_ |
14 | #define _SELINUX_CONDITIONAL_H_ | 14 | #define _SELINUX_CONDITIONAL_H_ |
15 | 15 | ||
16 | int security_get_bools(int *len, char ***names, int **values); | 16 | #include "security.h" |
17 | 17 | ||
18 | int security_set_bools(int len, int *values); | 18 | int security_get_bools(struct selinux_state *state, |
19 | int *len, char ***names, int **values); | ||
19 | 20 | ||
20 | int security_get_bool_value(int index); | 21 | int security_set_bools(struct selinux_state *state, |
22 | int len, int *values); | ||
23 | |||
24 | int security_get_bool_value(struct selinux_state *state, | ||
25 | int index); | ||
21 | 26 | ||
22 | #endif | 27 | #endif |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index e77a5e307955..8671de09c363 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/skbuff.h> | 32 | #include <linux/skbuff.h> |
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <net/request_sock.h> | 34 | #include <net/request_sock.h> |
35 | #include <net/sctp/structs.h> | ||
35 | 36 | ||
36 | #include "avc.h" | 37 | #include "avc.h" |
37 | #include "objsec.h" | 38 | #include "objsec.h" |
@@ -52,9 +53,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | |||
52 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | 53 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, |
53 | u16 family, | 54 | u16 family, |
54 | u32 sid); | 55 | u32 sid); |
55 | 56 | int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, | |
57 | struct sk_buff *skb); | ||
56 | int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); | 58 | int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); |
57 | void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); | 59 | void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); |
60 | void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk); | ||
58 | int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); | 61 | int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); |
59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 62 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
60 | struct sk_buff *skb, | 63 | struct sk_buff *skb, |
@@ -64,6 +67,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, | |||
64 | int level, | 67 | int level, |
65 | int optname); | 68 | int optname); |
66 | int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr); | 69 | int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr); |
70 | int selinux_netlbl_socket_connect_locked(struct sock *sk, | ||
71 | struct sockaddr *addr); | ||
67 | 72 | ||
68 | #else | 73 | #else |
69 | static inline void selinux_netlbl_cache_invalidate(void) | 74 | static inline void selinux_netlbl_cache_invalidate(void) |
@@ -113,6 +118,11 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk, | |||
113 | return 0; | 118 | return 0; |
114 | } | 119 | } |
115 | 120 | ||
121 | static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, | ||
122 | struct sk_buff *skb) | ||
123 | { | ||
124 | return 0; | ||
125 | } | ||
116 | static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, | 126 | static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, |
117 | u16 family) | 127 | u16 family) |
118 | { | 128 | { |
@@ -122,6 +132,11 @@ static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) | |||
122 | { | 132 | { |
123 | return; | 133 | return; |
124 | } | 134 | } |
135 | static inline void selinux_netlbl_sctp_sk_clone(struct sock *sk, | ||
136 | struct sock *newsk) | ||
137 | { | ||
138 | return; | ||
139 | } | ||
125 | static inline int selinux_netlbl_socket_post_create(struct sock *sk, | 140 | static inline int selinux_netlbl_socket_post_create(struct sock *sk, |
126 | u16 family) | 141 | u16 family) |
127 | { | 142 | { |
@@ -145,6 +160,11 @@ static inline int selinux_netlbl_socket_connect(struct sock *sk, | |||
145 | { | 160 | { |
146 | return 0; | 161 | return 0; |
147 | } | 162 | } |
163 | static inline int selinux_netlbl_socket_connect_locked(struct sock *sk, | ||
164 | struct sockaddr *addr) | ||
165 | { | ||
166 | return 0; | ||
167 | } | ||
148 | #endif /* CONFIG_NETLABEL */ | 168 | #endif /* CONFIG_NETLABEL */ |
149 | 169 | ||
150 | #endif | 170 | #endif |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 3d54468ce334..cc5e26b0161b 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -130,6 +130,10 @@ struct sk_security_struct { | |||
130 | u32 sid; /* SID of this object */ | 130 | u32 sid; /* SID of this object */ |
131 | u32 peer_sid; /* SID of peer */ | 131 | u32 peer_sid; /* SID of peer */ |
132 | u16 sclass; /* sock security class */ | 132 | u16 sclass; /* sock security class */ |
133 | enum { /* SCTP association state */ | ||
134 | SCTP_ASSOC_UNSET = 0, | ||
135 | SCTP_ASSOC_SET, | ||
136 | } sctp_assoc_state; | ||
133 | }; | 137 | }; |
134 | 138 | ||
135 | struct tun_security_struct { | 139 | struct tun_security_struct { |
@@ -154,6 +158,4 @@ struct bpf_security_struct { | |||
154 | u32 sid; /*SID of bpf obj creater*/ | 158 | u32 sid; /*SID of bpf obj creater*/ |
155 | }; | 159 | }; |
156 | 160 | ||
157 | extern unsigned int selinux_checkreqprot; | ||
158 | |||
159 | #endif /* _SELINUX_OBJSEC_H_ */ | 161 | #endif /* _SELINUX_OBJSEC_H_ */ |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 02f0412d42f2..23e762d529fa 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/dcache.h> | 13 | #include <linux/dcache.h> |
14 | #include <linux/magic.h> | 14 | #include <linux/magic.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/refcount.h> | ||
17 | #include <linux/workqueue.h> | ||
16 | #include "flask.h" | 18 | #include "flask.h" |
17 | 19 | ||
18 | #define SECSID_NULL 0x00000000 /* unspecified SID */ | 20 | #define SECSID_NULL 0x00000000 /* unspecified SID */ |
@@ -81,13 +83,6 @@ enum { | |||
81 | 83 | ||
82 | extern char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX]; | 84 | extern char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX]; |
83 | 85 | ||
84 | extern int selinux_policycap_netpeer; | ||
85 | extern int selinux_policycap_openperm; | ||
86 | extern int selinux_policycap_extsockclass; | ||
87 | extern int selinux_policycap_alwaysnetwork; | ||
88 | extern int selinux_policycap_cgroupseclabel; | ||
89 | extern int selinux_policycap_nnp_nosuid_transition; | ||
90 | |||
91 | /* | 86 | /* |
92 | * type_datum properties | 87 | * type_datum properties |
93 | * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY | 88 | * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY |
@@ -98,13 +93,98 @@ extern int selinux_policycap_nnp_nosuid_transition; | |||
98 | /* limitation of boundary depth */ | 93 | /* limitation of boundary depth */ |
99 | #define POLICYDB_BOUNDS_MAXDEPTH 4 | 94 | #define POLICYDB_BOUNDS_MAXDEPTH 4 |
100 | 95 | ||
101 | int security_mls_enabled(void); | 96 | struct selinux_avc; |
97 | struct selinux_ss; | ||
98 | |||
99 | struct selinux_state { | ||
100 | bool disabled; | ||
101 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | ||
102 | bool enforcing; | ||
103 | #endif | ||
104 | bool checkreqprot; | ||
105 | bool initialized; | ||
106 | bool policycap[__POLICYDB_CAPABILITY_MAX]; | ||
107 | struct selinux_avc *avc; | ||
108 | struct selinux_ss *ss; | ||
109 | }; | ||
110 | |||
111 | void selinux_ss_init(struct selinux_ss **ss); | ||
112 | void selinux_avc_init(struct selinux_avc **avc); | ||
113 | |||
114 | extern struct selinux_state selinux_state; | ||
115 | |||
116 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | ||
117 | static inline bool enforcing_enabled(struct selinux_state *state) | ||
118 | { | ||
119 | return state->enforcing; | ||
120 | } | ||
121 | |||
122 | static inline void enforcing_set(struct selinux_state *state, bool value) | ||
123 | { | ||
124 | state->enforcing = value; | ||
125 | } | ||
126 | #else | ||
127 | static inline bool enforcing_enabled(struct selinux_state *state) | ||
128 | { | ||
129 | return true; | ||
130 | } | ||
131 | |||
132 | static inline void enforcing_set(struct selinux_state *state, bool value) | ||
133 | { | ||
134 | } | ||
135 | #endif | ||
136 | |||
137 | static inline bool selinux_policycap_netpeer(void) | ||
138 | { | ||
139 | struct selinux_state *state = &selinux_state; | ||
140 | |||
141 | return state->policycap[POLICYDB_CAPABILITY_NETPEER]; | ||
142 | } | ||
143 | |||
144 | static inline bool selinux_policycap_openperm(void) | ||
145 | { | ||
146 | struct selinux_state *state = &selinux_state; | ||
147 | |||
148 | return state->policycap[POLICYDB_CAPABILITY_OPENPERM]; | ||
149 | } | ||
102 | 150 | ||
103 | int security_load_policy(void *data, size_t len); | 151 | static inline bool selinux_policycap_extsockclass(void) |
104 | int security_read_policy(void **data, size_t *len); | 152 | { |
105 | size_t security_policydb_len(void); | 153 | struct selinux_state *state = &selinux_state; |
154 | |||
155 | return state->policycap[POLICYDB_CAPABILITY_EXTSOCKCLASS]; | ||
156 | } | ||
106 | 157 | ||
107 | int security_policycap_supported(unsigned int req_cap); | 158 | static inline bool selinux_policycap_alwaysnetwork(void) |
159 | { | ||
160 | struct selinux_state *state = &selinux_state; | ||
161 | |||
162 | return state->policycap[POLICYDB_CAPABILITY_ALWAYSNETWORK]; | ||
163 | } | ||
164 | |||
165 | static inline bool selinux_policycap_cgroupseclabel(void) | ||
166 | { | ||
167 | struct selinux_state *state = &selinux_state; | ||
168 | |||
169 | return state->policycap[POLICYDB_CAPABILITY_CGROUPSECLABEL]; | ||
170 | } | ||
171 | |||
172 | static inline bool selinux_policycap_nnp_nosuid_transition(void) | ||
173 | { | ||
174 | struct selinux_state *state = &selinux_state; | ||
175 | |||
176 | return state->policycap[POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION]; | ||
177 | } | ||
178 | |||
179 | int security_mls_enabled(struct selinux_state *state); | ||
180 | int security_load_policy(struct selinux_state *state, | ||
181 | void *data, size_t len); | ||
182 | int security_read_policy(struct selinux_state *state, | ||
183 | void **data, size_t *len); | ||
184 | size_t security_policydb_len(struct selinux_state *state); | ||
185 | |||
186 | int security_policycap_supported(struct selinux_state *state, | ||
187 | unsigned int req_cap); | ||
108 | 188 | ||
109 | #define SEL_VEC_MAX 32 | 189 | #define SEL_VEC_MAX 32 |
110 | struct av_decision { | 190 | struct av_decision { |
@@ -141,76 +221,100 @@ struct extended_perms { | |||
141 | /* definitions of av_decision.flags */ | 221 | /* definitions of av_decision.flags */ |
142 | #define AVD_FLAGS_PERMISSIVE 0x0001 | 222 | #define AVD_FLAGS_PERMISSIVE 0x0001 |
143 | 223 | ||
144 | void security_compute_av(u32 ssid, u32 tsid, | 224 | void security_compute_av(struct selinux_state *state, |
225 | u32 ssid, u32 tsid, | ||
145 | u16 tclass, struct av_decision *avd, | 226 | u16 tclass, struct av_decision *avd, |
146 | struct extended_perms *xperms); | 227 | struct extended_perms *xperms); |
147 | 228 | ||
148 | void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, | 229 | void security_compute_xperms_decision(struct selinux_state *state, |
149 | u8 driver, struct extended_perms_decision *xpermd); | 230 | u32 ssid, u32 tsid, u16 tclass, |
231 | u8 driver, | ||
232 | struct extended_perms_decision *xpermd); | ||
150 | 233 | ||
151 | void security_compute_av_user(u32 ssid, u32 tsid, | 234 | void security_compute_av_user(struct selinux_state *state, |
152 | u16 tclass, struct av_decision *avd); | 235 | u32 ssid, u32 tsid, |
236 | u16 tclass, struct av_decision *avd); | ||
153 | 237 | ||
154 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | 238 | int security_transition_sid(struct selinux_state *state, |
239 | u32 ssid, u32 tsid, u16 tclass, | ||
155 | const struct qstr *qstr, u32 *out_sid); | 240 | const struct qstr *qstr, u32 *out_sid); |
156 | 241 | ||
157 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, | 242 | int security_transition_sid_user(struct selinux_state *state, |
243 | u32 ssid, u32 tsid, u16 tclass, | ||
158 | const char *objname, u32 *out_sid); | 244 | const char *objname, u32 *out_sid); |
159 | 245 | ||
160 | int security_member_sid(u32 ssid, u32 tsid, | 246 | int security_member_sid(struct selinux_state *state, u32 ssid, u32 tsid, |
161 | u16 tclass, u32 *out_sid); | 247 | u16 tclass, u32 *out_sid); |
162 | 248 | ||
163 | int security_change_sid(u32 ssid, u32 tsid, | 249 | int security_change_sid(struct selinux_state *state, u32 ssid, u32 tsid, |
164 | u16 tclass, u32 *out_sid); | 250 | u16 tclass, u32 *out_sid); |
165 | 251 | ||
166 | int security_sid_to_context(u32 sid, char **scontext, | 252 | int security_sid_to_context(struct selinux_state *state, u32 sid, |
167 | u32 *scontext_len); | 253 | char **scontext, u32 *scontext_len); |
168 | 254 | ||
169 | int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len); | 255 | int security_sid_to_context_force(struct selinux_state *state, |
256 | u32 sid, char **scontext, u32 *scontext_len); | ||
170 | 257 | ||
171 | int security_context_to_sid(const char *scontext, u32 scontext_len, | 258 | int security_context_to_sid(struct selinux_state *state, |
259 | const char *scontext, u32 scontext_len, | ||
172 | u32 *out_sid, gfp_t gfp); | 260 | u32 *out_sid, gfp_t gfp); |
173 | 261 | ||
174 | int security_context_str_to_sid(const char *scontext, u32 *out_sid, gfp_t gfp); | 262 | int security_context_str_to_sid(struct selinux_state *state, |
263 | const char *scontext, u32 *out_sid, gfp_t gfp); | ||
175 | 264 | ||
176 | int security_context_to_sid_default(const char *scontext, u32 scontext_len, | 265 | int security_context_to_sid_default(struct selinux_state *state, |
266 | const char *scontext, u32 scontext_len, | ||
177 | u32 *out_sid, u32 def_sid, gfp_t gfp_flags); | 267 | u32 *out_sid, u32 def_sid, gfp_t gfp_flags); |
178 | 268 | ||
179 | int security_context_to_sid_force(const char *scontext, u32 scontext_len, | 269 | int security_context_to_sid_force(struct selinux_state *state, |
270 | const char *scontext, u32 scontext_len, | ||
180 | u32 *sid); | 271 | u32 *sid); |
181 | 272 | ||
182 | int security_get_user_sids(u32 callsid, char *username, | 273 | int security_get_user_sids(struct selinux_state *state, |
274 | u32 callsid, char *username, | ||
183 | u32 **sids, u32 *nel); | 275 | u32 **sids, u32 *nel); |
184 | 276 | ||
185 | int security_port_sid(u8 protocol, u16 port, u32 *out_sid); | 277 | int security_port_sid(struct selinux_state *state, |
278 | u8 protocol, u16 port, u32 *out_sid); | ||
186 | 279 | ||
187 | int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid); | 280 | int security_ib_pkey_sid(struct selinux_state *state, |
281 | u64 subnet_prefix, u16 pkey_num, u32 *out_sid); | ||
188 | 282 | ||
189 | int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid); | 283 | int security_ib_endport_sid(struct selinux_state *state, |
284 | const char *dev_name, u8 port_num, u32 *out_sid); | ||
190 | 285 | ||
191 | int security_netif_sid(char *name, u32 *if_sid); | 286 | int security_netif_sid(struct selinux_state *state, |
287 | char *name, u32 *if_sid); | ||
192 | 288 | ||
193 | int security_node_sid(u16 domain, void *addr, u32 addrlen, | 289 | int security_node_sid(struct selinux_state *state, |
194 | u32 *out_sid); | 290 | u16 domain, void *addr, u32 addrlen, |
291 | u32 *out_sid); | ||
195 | 292 | ||
196 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 293 | int security_validate_transition(struct selinux_state *state, |
294 | u32 oldsid, u32 newsid, u32 tasksid, | ||
197 | u16 tclass); | 295 | u16 tclass); |
198 | 296 | ||
199 | int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid, | 297 | int security_validate_transition_user(struct selinux_state *state, |
298 | u32 oldsid, u32 newsid, u32 tasksid, | ||
200 | u16 tclass); | 299 | u16 tclass); |
201 | 300 | ||
202 | int security_bounded_transition(u32 oldsid, u32 newsid); | 301 | int security_bounded_transition(struct selinux_state *state, |
302 | u32 oldsid, u32 newsid); | ||
203 | 303 | ||
204 | int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); | 304 | int security_sid_mls_copy(struct selinux_state *state, |
305 | u32 sid, u32 mls_sid, u32 *new_sid); | ||
205 | 306 | ||
206 | int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | 307 | int security_net_peersid_resolve(struct selinux_state *state, |
308 | u32 nlbl_sid, u32 nlbl_type, | ||
207 | u32 xfrm_sid, | 309 | u32 xfrm_sid, |
208 | u32 *peer_sid); | 310 | u32 *peer_sid); |
209 | 311 | ||
210 | int security_get_classes(char ***classes, int *nclasses); | 312 | int security_get_classes(struct selinux_state *state, |
211 | int security_get_permissions(char *class, char ***perms, int *nperms); | 313 | char ***classes, int *nclasses); |
212 | int security_get_reject_unknown(void); | 314 | int security_get_permissions(struct selinux_state *state, |
213 | int security_get_allow_unknown(void); | 315 | char *class, char ***perms, int *nperms); |
316 | int security_get_reject_unknown(struct selinux_state *state); | ||
317 | int security_get_allow_unknown(struct selinux_state *state); | ||
214 | 318 | ||
215 | #define SECURITY_FS_USE_XATTR 1 /* use xattr */ | 319 | #define SECURITY_FS_USE_XATTR 1 /* use xattr */ |
216 | #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ | 320 | #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ |
@@ -221,27 +325,31 @@ int security_get_allow_unknown(void); | |||
221 | #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ | 325 | #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ |
222 | #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ | 326 | #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ |
223 | 327 | ||
224 | int security_fs_use(struct super_block *sb); | 328 | int security_fs_use(struct selinux_state *state, struct super_block *sb); |
225 | 329 | ||
226 | int security_genfs_sid(const char *fstype, char *name, u16 sclass, | 330 | int security_genfs_sid(struct selinux_state *state, |
227 | u32 *sid); | 331 | const char *fstype, char *name, u16 sclass, |
332 | u32 *sid); | ||
228 | 333 | ||
229 | #ifdef CONFIG_NETLABEL | 334 | #ifdef CONFIG_NETLABEL |
230 | int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | 335 | int security_netlbl_secattr_to_sid(struct selinux_state *state, |
336 | struct netlbl_lsm_secattr *secattr, | ||
231 | u32 *sid); | 337 | u32 *sid); |
232 | 338 | ||
233 | int security_netlbl_sid_to_secattr(u32 sid, | 339 | int security_netlbl_sid_to_secattr(struct selinux_state *state, |
340 | u32 sid, | ||
234 | struct netlbl_lsm_secattr *secattr); | 341 | struct netlbl_lsm_secattr *secattr); |
235 | #else | 342 | #else |
236 | static inline int security_netlbl_secattr_to_sid( | 343 | static inline int security_netlbl_secattr_to_sid(struct selinux_state *state, |
237 | struct netlbl_lsm_secattr *secattr, | 344 | struct netlbl_lsm_secattr *secattr, |
238 | u32 *sid) | 345 | u32 *sid) |
239 | { | 346 | { |
240 | return -EIDRM; | 347 | return -EIDRM; |
241 | } | 348 | } |
242 | 349 | ||
243 | static inline int security_netlbl_sid_to_secattr(u32 sid, | 350 | static inline int security_netlbl_sid_to_secattr(struct selinux_state *state, |
244 | struct netlbl_lsm_secattr *secattr) | 351 | u32 sid, |
352 | struct netlbl_lsm_secattr *secattr) | ||
245 | { | 353 | { |
246 | return -ENOENT; | 354 | return -ENOENT; |
247 | } | 355 | } |
@@ -252,7 +360,7 @@ const char *security_get_initial_sid_context(u32 sid); | |||
252 | /* | 360 | /* |
253 | * status notifier using mmap interface | 361 | * status notifier using mmap interface |
254 | */ | 362 | */ |
255 | extern struct page *selinux_kernel_status_page(void); | 363 | extern struct page *selinux_kernel_status_page(struct selinux_state *state); |
256 | 364 | ||
257 | #define SELINUX_KERNEL_STATUS_VERSION 1 | 365 | #define SELINUX_KERNEL_STATUS_VERSION 1 |
258 | struct selinux_kernel_status { | 366 | struct selinux_kernel_status { |
@@ -266,10 +374,12 @@ struct selinux_kernel_status { | |||
266 | */ | 374 | */ |
267 | } __packed; | 375 | } __packed; |
268 | 376 | ||
269 | extern void selinux_status_update_setenforce(int enforcing); | 377 | extern void selinux_status_update_setenforce(struct selinux_state *state, |
270 | extern void selinux_status_update_policyload(int seqno); | 378 | int enforcing); |
379 | extern void selinux_status_update_policyload(struct selinux_state *state, | ||
380 | int seqno); | ||
271 | extern void selinux_complete_init(void); | 381 | extern void selinux_complete_init(void); |
272 | extern int selinux_disable(void); | 382 | extern int selinux_disable(struct selinux_state *state); |
273 | extern void exit_sel_fs(void); | 383 | extern void exit_sel_fs(void); |
274 | extern struct path selinux_null; | 384 | extern struct path selinux_null; |
275 | extern struct vfsmount *selinuxfs_mount; | 385 | extern struct vfsmount *selinuxfs_mount; |
@@ -277,5 +387,8 @@ extern void selnl_notify_setenforce(int val); | |||
277 | extern void selnl_notify_policyload(u32 seqno); | 387 | extern void selnl_notify_policyload(u32 seqno); |
278 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 388 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
279 | 389 | ||
280 | #endif /* _SELINUX_SECURITY_H_ */ | 390 | extern void avtab_cache_init(void); |
391 | extern void ebitmap_cache_init(void); | ||
392 | extern void hashtab_cache_init(void); | ||
281 | 393 | ||
394 | #endif /* _SELINUX_SECURITY_H_ */ | ||
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index e607b4473ef6..ac65f7417413 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -163,7 +163,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) | |||
163 | ret = -ENOMEM; | 163 | ret = -ENOMEM; |
164 | goto out; | 164 | goto out; |
165 | } | 165 | } |
166 | ret = security_netif_sid(dev->name, &new->nsec.sid); | 166 | ret = security_netif_sid(&selinux_state, dev->name, &new->nsec.sid); |
167 | if (ret != 0) | 167 | if (ret != 0) |
168 | goto out; | 168 | goto out; |
169 | new->nsec.ns = ns; | 169 | new->nsec.ns = ns; |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2c297b995b16..186e727b737b 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -59,7 +59,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, | |||
59 | { | 59 | { |
60 | int rc; | 60 | int rc; |
61 | 61 | ||
62 | rc = security_netlbl_secattr_to_sid(secattr, sid); | 62 | rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid); |
63 | if (rc == 0 && | 63 | if (rc == 0 && |
64 | (secattr->flags & NETLBL_SECATTR_CACHEABLE) && | 64 | (secattr->flags & NETLBL_SECATTR_CACHEABLE) && |
65 | (secattr->flags & NETLBL_SECATTR_CACHE)) | 65 | (secattr->flags & NETLBL_SECATTR_CACHE)) |
@@ -90,7 +90,8 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) | |||
90 | secattr = netlbl_secattr_alloc(GFP_ATOMIC); | 90 | secattr = netlbl_secattr_alloc(GFP_ATOMIC); |
91 | if (secattr == NULL) | 91 | if (secattr == NULL) |
92 | return NULL; | 92 | return NULL; |
93 | rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); | 93 | rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid, |
94 | secattr); | ||
94 | if (rc != 0) { | 95 | if (rc != 0) { |
95 | netlbl_secattr_free(secattr); | 96 | netlbl_secattr_free(secattr); |
96 | return NULL; | 97 | return NULL; |
@@ -249,6 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | |||
249 | sk = skb_to_full_sk(skb); | 250 | sk = skb_to_full_sk(skb); |
250 | if (sk != NULL) { | 251 | if (sk != NULL) { |
251 | struct sk_security_struct *sksec = sk->sk_security; | 252 | struct sk_security_struct *sksec = sk->sk_security; |
253 | |||
252 | if (sksec->nlbl_state != NLBL_REQSKB) | 254 | if (sksec->nlbl_state != NLBL_REQSKB) |
253 | return 0; | 255 | return 0; |
254 | secattr = selinux_netlbl_sock_getattr(sk, sid); | 256 | secattr = selinux_netlbl_sock_getattr(sk, sid); |
@@ -256,7 +258,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | |||
256 | if (secattr == NULL) { | 258 | if (secattr == NULL) { |
257 | secattr = &secattr_storage; | 259 | secattr = &secattr_storage; |
258 | netlbl_secattr_init(secattr); | 260 | netlbl_secattr_init(secattr); |
259 | rc = security_netlbl_sid_to_secattr(sid, secattr); | 261 | rc = security_netlbl_sid_to_secattr(&selinux_state, sid, |
262 | secattr); | ||
260 | if (rc != 0) | 263 | if (rc != 0) |
261 | goto skbuff_setsid_return; | 264 | goto skbuff_setsid_return; |
262 | } | 265 | } |
@@ -270,6 +273,62 @@ skbuff_setsid_return: | |||
270 | } | 273 | } |
271 | 274 | ||
272 | /** | 275 | /** |
276 | * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association. | ||
277 | * @ep: incoming association endpoint. | ||
278 | * @skb: the packet. | ||
279 | * | ||
280 | * Description: | ||
281 | * A new incoming connection is represented by @ep, ...... | ||
282 | * Returns zero on success, negative values on failure. | ||
283 | * | ||
284 | */ | ||
285 | int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, | ||
286 | struct sk_buff *skb) | ||
287 | { | ||
288 | int rc; | ||
289 | struct netlbl_lsm_secattr secattr; | ||
290 | struct sk_security_struct *sksec = ep->base.sk->sk_security; | ||
291 | struct sockaddr *addr; | ||
292 | struct sockaddr_in addr4; | ||
293 | #if IS_ENABLED(CONFIG_IPV6) | ||
294 | struct sockaddr_in6 addr6; | ||
295 | #endif | ||
296 | |||
297 | if (ep->base.sk->sk_family != PF_INET && | ||
298 | ep->base.sk->sk_family != PF_INET6) | ||
299 | return 0; | ||
300 | |||
301 | netlbl_secattr_init(&secattr); | ||
302 | rc = security_netlbl_sid_to_secattr(&selinux_state, | ||
303 | ep->secid, &secattr); | ||
304 | if (rc != 0) | ||
305 | goto assoc_request_return; | ||
306 | |||
307 | /* Move skb hdr address info to a struct sockaddr and then call | ||
308 | * netlbl_conn_setattr(). | ||
309 | */ | ||
310 | if (ip_hdr(skb)->version == 4) { | ||
311 | addr4.sin_family = AF_INET; | ||
312 | addr4.sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
313 | addr = (struct sockaddr *)&addr4; | ||
314 | #if IS_ENABLED(CONFIG_IPV6) | ||
315 | } else { | ||
316 | addr6.sin6_family = AF_INET6; | ||
317 | addr6.sin6_addr = ipv6_hdr(skb)->saddr; | ||
318 | addr = (struct sockaddr *)&addr6; | ||
319 | #endif | ||
320 | } | ||
321 | |||
322 | rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr); | ||
323 | if (rc == 0) | ||
324 | sksec->nlbl_state = NLBL_LABELED; | ||
325 | |||
326 | assoc_request_return: | ||
327 | netlbl_secattr_destroy(&secattr); | ||
328 | return rc; | ||
329 | } | ||
330 | |||
331 | /** | ||
273 | * selinux_netlbl_inet_conn_request - Label an incoming stream connection | 332 | * selinux_netlbl_inet_conn_request - Label an incoming stream connection |
274 | * @req: incoming connection request socket | 333 | * @req: incoming connection request socket |
275 | * | 334 | * |
@@ -289,7 +348,8 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) | |||
289 | return 0; | 348 | return 0; |
290 | 349 | ||
291 | netlbl_secattr_init(&secattr); | 350 | netlbl_secattr_init(&secattr); |
292 | rc = security_netlbl_sid_to_secattr(req->secid, &secattr); | 351 | rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid, |
352 | &secattr); | ||
293 | if (rc != 0) | 353 | if (rc != 0) |
294 | goto inet_conn_request_return; | 354 | goto inet_conn_request_return; |
295 | rc = netlbl_req_setattr(req, &secattr); | 355 | rc = netlbl_req_setattr(req, &secattr); |
@@ -319,6 +379,22 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) | |||
319 | } | 379 | } |
320 | 380 | ||
321 | /** | 381 | /** |
382 | * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock | ||
383 | * @sk: current sock | ||
384 | * @newsk: the new sock | ||
385 | * | ||
386 | * Description: | ||
387 | * Called whenever a new socket is created by accept(2) or sctp_peeloff(3). | ||
388 | */ | ||
389 | void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) | ||
390 | { | ||
391 | struct sk_security_struct *sksec = sk->sk_security; | ||
392 | struct sk_security_struct *newsksec = newsk->sk_security; | ||
393 | |||
394 | newsksec->nlbl_state = sksec->nlbl_state; | ||
395 | } | ||
396 | |||
397 | /** | ||
322 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel | 398 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel |
323 | * @sock: the socket to label | 399 | * @sock: the socket to label |
324 | * @family: protocol family | 400 | * @family: protocol family |
@@ -402,7 +478,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
402 | perm = RAWIP_SOCKET__RECVFROM; | 478 | perm = RAWIP_SOCKET__RECVFROM; |
403 | } | 479 | } |
404 | 480 | ||
405 | rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); | 481 | rc = avc_has_perm(&selinux_state, |
482 | sksec->sid, nlbl_sid, sksec->sclass, perm, ad); | ||
406 | if (rc == 0) | 483 | if (rc == 0) |
407 | return 0; | 484 | return 0; |
408 | 485 | ||
@@ -469,7 +546,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, | |||
469 | } | 546 | } |
470 | 547 | ||
471 | /** | 548 | /** |
472 | * selinux_netlbl_socket_connect - Label a client-side socket on connect | 549 | * selinux_netlbl_socket_connect_helper - Help label a client-side socket on |
550 | * connect | ||
473 | * @sk: the socket to label | 551 | * @sk: the socket to label |
474 | * @addr: the destination address | 552 | * @addr: the destination address |
475 | * | 553 | * |
@@ -478,18 +556,13 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, | |||
478 | * Returns zero values on success, negative values on failure. | 556 | * Returns zero values on success, negative values on failure. |
479 | * | 557 | * |
480 | */ | 558 | */ |
481 | int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) | 559 | static int selinux_netlbl_socket_connect_helper(struct sock *sk, |
560 | struct sockaddr *addr) | ||
482 | { | 561 | { |
483 | int rc; | 562 | int rc; |
484 | struct sk_security_struct *sksec = sk->sk_security; | 563 | struct sk_security_struct *sksec = sk->sk_security; |
485 | struct netlbl_lsm_secattr *secattr; | 564 | struct netlbl_lsm_secattr *secattr; |
486 | 565 | ||
487 | if (sksec->nlbl_state != NLBL_REQSKB && | ||
488 | sksec->nlbl_state != NLBL_CONNLABELED) | ||
489 | return 0; | ||
490 | |||
491 | lock_sock(sk); | ||
492 | |||
493 | /* connected sockets are allowed to disconnect when the address family | 566 | /* connected sockets are allowed to disconnect when the address family |
494 | * is set to AF_UNSPEC, if that is what is happening we want to reset | 567 | * is set to AF_UNSPEC, if that is what is happening we want to reset |
495 | * the socket */ | 568 | * the socket */ |
@@ -497,18 +570,61 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) | |||
497 | netlbl_sock_delattr(sk); | 570 | netlbl_sock_delattr(sk); |
498 | sksec->nlbl_state = NLBL_REQSKB; | 571 | sksec->nlbl_state = NLBL_REQSKB; |
499 | rc = 0; | 572 | rc = 0; |
500 | goto socket_connect_return; | 573 | return rc; |
501 | } | 574 | } |
502 | secattr = selinux_netlbl_sock_genattr(sk); | 575 | secattr = selinux_netlbl_sock_genattr(sk); |
503 | if (secattr == NULL) { | 576 | if (secattr == NULL) { |
504 | rc = -ENOMEM; | 577 | rc = -ENOMEM; |
505 | goto socket_connect_return; | 578 | return rc; |
506 | } | 579 | } |
507 | rc = netlbl_conn_setattr(sk, addr, secattr); | 580 | rc = netlbl_conn_setattr(sk, addr, secattr); |
508 | if (rc == 0) | 581 | if (rc == 0) |
509 | sksec->nlbl_state = NLBL_CONNLABELED; | 582 | sksec->nlbl_state = NLBL_CONNLABELED; |
510 | 583 | ||
511 | socket_connect_return: | 584 | return rc; |
585 | } | ||
586 | |||
587 | /** | ||
588 | * selinux_netlbl_socket_connect_locked - Label a client-side socket on | ||
589 | * connect | ||
590 | * @sk: the socket to label | ||
591 | * @addr: the destination address | ||
592 | * | ||
593 | * Description: | ||
594 | * Attempt to label a connected socket that already has the socket locked | ||
595 | * with NetLabel using the given address. | ||
596 | * Returns zero values on success, negative values on failure. | ||
597 | * | ||
598 | */ | ||
599 | int selinux_netlbl_socket_connect_locked(struct sock *sk, | ||
600 | struct sockaddr *addr) | ||
601 | { | ||
602 | struct sk_security_struct *sksec = sk->sk_security; | ||
603 | |||
604 | if (sksec->nlbl_state != NLBL_REQSKB && | ||
605 | sksec->nlbl_state != NLBL_CONNLABELED) | ||
606 | return 0; | ||
607 | |||
608 | return selinux_netlbl_socket_connect_helper(sk, addr); | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * selinux_netlbl_socket_connect - Label a client-side socket on connect | ||
613 | * @sk: the socket to label | ||
614 | * @addr: the destination address | ||
615 | * | ||
616 | * Description: | ||
617 | * Attempt to label a connected socket with NetLabel using the given address. | ||
618 | * Returns zero values on success, negative values on failure. | ||
619 | * | ||
620 | */ | ||
621 | int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) | ||
622 | { | ||
623 | int rc; | ||
624 | |||
625 | lock_sock(sk); | ||
626 | rc = selinux_netlbl_socket_connect_locked(sk, addr); | ||
512 | release_sock(sk); | 627 | release_sock(sk); |
628 | |||
513 | return rc; | 629 | return rc; |
514 | } | 630 | } |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index da923f89d2a9..6dd89b89bc1f 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -215,12 +215,12 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) | |||
215 | goto out; | 215 | goto out; |
216 | switch (family) { | 216 | switch (family) { |
217 | case PF_INET: | 217 | case PF_INET: |
218 | ret = security_node_sid(PF_INET, | 218 | ret = security_node_sid(&selinux_state, PF_INET, |
219 | addr, sizeof(struct in_addr), sid); | 219 | addr, sizeof(struct in_addr), sid); |
220 | new->nsec.addr.ipv4 = *(__be32 *)addr; | 220 | new->nsec.addr.ipv4 = *(__be32 *)addr; |
221 | break; | 221 | break; |
222 | case PF_INET6: | 222 | case PF_INET6: |
223 | ret = security_node_sid(PF_INET6, | 223 | ret = security_node_sid(&selinux_state, PF_INET6, |
224 | addr, sizeof(struct in6_addr), sid); | 224 | addr, sizeof(struct in6_addr), sid); |
225 | new->nsec.addr.ipv6 = *(struct in6_addr *)addr; | 225 | new->nsec.addr.ipv6 = *(struct in6_addr *)addr; |
226 | break; | 226 | break; |
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 3311cc393cb4..9ed4c5064a5e 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -161,7 +161,7 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) | |||
161 | new = kzalloc(sizeof(*new), GFP_ATOMIC); | 161 | new = kzalloc(sizeof(*new), GFP_ATOMIC); |
162 | if (new == NULL) | 162 | if (new == NULL) |
163 | goto out; | 163 | goto out; |
164 | ret = security_port_sid(protocol, pnum, sid); | 164 | ret = security_port_sid(&selinux_state, protocol, pnum, sid); |
165 | if (ret != 0) | 165 | if (ret != 0) |
166 | goto out; | 166 | goto out; |
167 | 167 | ||
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 00eed842c491..4be683eeba01 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/mount.h> | ||
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/string.h> | 25 | #include <linux/string.h> |
@@ -41,34 +42,6 @@ | |||
41 | #include "objsec.h" | 42 | #include "objsec.h" |
42 | #include "conditional.h" | 43 | #include "conditional.h" |
43 | 44 | ||
44 | unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; | ||
45 | |||
46 | static int __init checkreqprot_setup(char *str) | ||
47 | { | ||
48 | unsigned long checkreqprot; | ||
49 | if (!kstrtoul(str, 0, &checkreqprot)) | ||
50 | selinux_checkreqprot = checkreqprot ? 1 : 0; | ||
51 | return 1; | ||
52 | } | ||
53 | __setup("checkreqprot=", checkreqprot_setup); | ||
54 | |||
55 | static DEFINE_MUTEX(sel_mutex); | ||
56 | |||
57 | /* global data for booleans */ | ||
58 | static struct dentry *bool_dir; | ||
59 | static int bool_num; | ||
60 | static char **bool_pending_names; | ||
61 | static int *bool_pending_values; | ||
62 | |||
63 | /* global data for classes */ | ||
64 | static struct dentry *class_dir; | ||
65 | static unsigned long last_class_ino; | ||
66 | |||
67 | static char policy_opened; | ||
68 | |||
69 | /* global data for policy capabilities */ | ||
70 | static struct dentry *policycap_dir; | ||
71 | |||
72 | enum sel_inos { | 45 | enum sel_inos { |
73 | SEL_ROOT_INO = 2, | 46 | SEL_ROOT_INO = 2, |
74 | SEL_LOAD, /* load policy */ | 47 | SEL_LOAD, /* load policy */ |
@@ -93,7 +66,51 @@ enum sel_inos { | |||
93 | SEL_INO_NEXT, /* The next inode number to use */ | 66 | SEL_INO_NEXT, /* The next inode number to use */ |
94 | }; | 67 | }; |
95 | 68 | ||
96 | static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | 69 | struct selinux_fs_info { |
70 | struct dentry *bool_dir; | ||
71 | unsigned int bool_num; | ||
72 | char **bool_pending_names; | ||
73 | unsigned int *bool_pending_values; | ||
74 | struct dentry *class_dir; | ||
75 | unsigned long last_class_ino; | ||
76 | bool policy_opened; | ||
77 | struct dentry *policycap_dir; | ||
78 | struct mutex mutex; | ||
79 | unsigned long last_ino; | ||
80 | struct selinux_state *state; | ||
81 | struct super_block *sb; | ||
82 | }; | ||
83 | |||
84 | static int selinux_fs_info_create(struct super_block *sb) | ||
85 | { | ||
86 | struct selinux_fs_info *fsi; | ||
87 | |||
88 | fsi = kzalloc(sizeof(*fsi), GFP_KERNEL); | ||
89 | if (!fsi) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | mutex_init(&fsi->mutex); | ||
93 | fsi->last_ino = SEL_INO_NEXT - 1; | ||
94 | fsi->state = &selinux_state; | ||
95 | fsi->sb = sb; | ||
96 | sb->s_fs_info = fsi; | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void selinux_fs_info_free(struct super_block *sb) | ||
101 | { | ||
102 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
103 | int i; | ||
104 | |||
105 | if (fsi) { | ||
106 | for (i = 0; i < fsi->bool_num; i++) | ||
107 | kfree(fsi->bool_pending_names[i]); | ||
108 | kfree(fsi->bool_pending_names); | ||
109 | kfree(fsi->bool_pending_values); | ||
110 | } | ||
111 | kfree(sb->s_fs_info); | ||
112 | sb->s_fs_info = NULL; | ||
113 | } | ||
97 | 114 | ||
98 | #define SEL_INITCON_INO_OFFSET 0x01000000 | 115 | #define SEL_INITCON_INO_OFFSET 0x01000000 |
99 | #define SEL_BOOL_INO_OFFSET 0x02000000 | 116 | #define SEL_BOOL_INO_OFFSET 0x02000000 |
@@ -105,10 +122,12 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | |||
105 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, | 122 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, |
106 | size_t count, loff_t *ppos) | 123 | size_t count, loff_t *ppos) |
107 | { | 124 | { |
125 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
108 | char tmpbuf[TMPBUFLEN]; | 126 | char tmpbuf[TMPBUFLEN]; |
109 | ssize_t length; | 127 | ssize_t length; |
110 | 128 | ||
111 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing); | 129 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
130 | enforcing_enabled(fsi->state)); | ||
112 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 131 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
113 | } | 132 | } |
114 | 133 | ||
@@ -117,9 +136,11 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
117 | size_t count, loff_t *ppos) | 136 | size_t count, loff_t *ppos) |
118 | 137 | ||
119 | { | 138 | { |
139 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
140 | struct selinux_state *state = fsi->state; | ||
120 | char *page = NULL; | 141 | char *page = NULL; |
121 | ssize_t length; | 142 | ssize_t length; |
122 | int new_value; | 143 | int old_value, new_value; |
123 | 144 | ||
124 | if (count >= PAGE_SIZE) | 145 | if (count >= PAGE_SIZE) |
125 | return -ENOMEM; | 146 | return -ENOMEM; |
@@ -138,23 +159,25 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
138 | 159 | ||
139 | new_value = !!new_value; | 160 | new_value = !!new_value; |
140 | 161 | ||
141 | if (new_value != selinux_enforcing) { | 162 | old_value = enforcing_enabled(state); |
142 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 163 | if (new_value != old_value) { |
164 | length = avc_has_perm(&selinux_state, | ||
165 | current_sid(), SECINITSID_SECURITY, | ||
143 | SECCLASS_SECURITY, SECURITY__SETENFORCE, | 166 | SECCLASS_SECURITY, SECURITY__SETENFORCE, |
144 | NULL); | 167 | NULL); |
145 | if (length) | 168 | if (length) |
146 | goto out; | 169 | goto out; |
147 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 170 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
148 | "enforcing=%d old_enforcing=%d auid=%u ses=%u", | 171 | "enforcing=%d old_enforcing=%d auid=%u ses=%u", |
149 | new_value, selinux_enforcing, | 172 | new_value, old_value, |
150 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 173 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
151 | audit_get_sessionid(current)); | 174 | audit_get_sessionid(current)); |
152 | selinux_enforcing = new_value; | 175 | enforcing_set(state, new_value); |
153 | if (selinux_enforcing) | 176 | if (new_value) |
154 | avc_ss_reset(0); | 177 | avc_ss_reset(state->avc, 0); |
155 | selnl_notify_setenforce(selinux_enforcing); | 178 | selnl_notify_setenforce(new_value); |
156 | selinux_status_update_setenforce(selinux_enforcing); | 179 | selinux_status_update_setenforce(state, new_value); |
157 | if (!selinux_enforcing) | 180 | if (!new_value) |
158 | call_lsm_notifier(LSM_POLICY_CHANGE, NULL); | 181 | call_lsm_notifier(LSM_POLICY_CHANGE, NULL); |
159 | } | 182 | } |
160 | length = count; | 183 | length = count; |
@@ -175,11 +198,14 @@ static const struct file_operations sel_enforce_ops = { | |||
175 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | 198 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, |
176 | size_t count, loff_t *ppos) | 199 | size_t count, loff_t *ppos) |
177 | { | 200 | { |
201 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
202 | struct selinux_state *state = fsi->state; | ||
178 | char tmpbuf[TMPBUFLEN]; | 203 | char tmpbuf[TMPBUFLEN]; |
179 | ssize_t length; | 204 | ssize_t length; |
180 | ino_t ino = file_inode(filp)->i_ino; | 205 | ino_t ino = file_inode(filp)->i_ino; |
181 | int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? | 206 | int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? |
182 | security_get_reject_unknown() : !security_get_allow_unknown(); | 207 | security_get_reject_unknown(state) : |
208 | !security_get_allow_unknown(state); | ||
183 | 209 | ||
184 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown); | 210 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown); |
185 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 211 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
@@ -192,7 +218,8 @@ static const struct file_operations sel_handle_unknown_ops = { | |||
192 | 218 | ||
193 | static int sel_open_handle_status(struct inode *inode, struct file *filp) | 219 | static int sel_open_handle_status(struct inode *inode, struct file *filp) |
194 | { | 220 | { |
195 | struct page *status = selinux_kernel_status_page(); | 221 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; |
222 | struct page *status = selinux_kernel_status_page(fsi->state); | ||
196 | 223 | ||
197 | if (!status) | 224 | if (!status) |
198 | return -ENOMEM; | 225 | return -ENOMEM; |
@@ -248,6 +275,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
248 | size_t count, loff_t *ppos) | 275 | size_t count, loff_t *ppos) |
249 | 276 | ||
250 | { | 277 | { |
278 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
251 | char *page; | 279 | char *page; |
252 | ssize_t length; | 280 | ssize_t length; |
253 | int new_value; | 281 | int new_value; |
@@ -268,7 +296,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
268 | goto out; | 296 | goto out; |
269 | 297 | ||
270 | if (new_value) { | 298 | if (new_value) { |
271 | length = selinux_disable(); | 299 | length = selinux_disable(fsi->state); |
272 | if (length) | 300 | if (length) |
273 | goto out; | 301 | goto out; |
274 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 302 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
@@ -307,9 +335,9 @@ static const struct file_operations sel_policyvers_ops = { | |||
307 | }; | 335 | }; |
308 | 336 | ||
309 | /* declaration for sel_write_load */ | 337 | /* declaration for sel_write_load */ |
310 | static int sel_make_bools(void); | 338 | static int sel_make_bools(struct selinux_fs_info *fsi); |
311 | static int sel_make_classes(void); | 339 | static int sel_make_classes(struct selinux_fs_info *fsi); |
312 | static int sel_make_policycap(void); | 340 | static int sel_make_policycap(struct selinux_fs_info *fsi); |
313 | 341 | ||
314 | /* declaration for sel_make_class_dirs */ | 342 | /* declaration for sel_make_class_dirs */ |
315 | static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | 343 | static struct dentry *sel_make_dir(struct dentry *dir, const char *name, |
@@ -318,11 +346,12 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | |||
318 | static ssize_t sel_read_mls(struct file *filp, char __user *buf, | 346 | static ssize_t sel_read_mls(struct file *filp, char __user *buf, |
319 | size_t count, loff_t *ppos) | 347 | size_t count, loff_t *ppos) |
320 | { | 348 | { |
349 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
321 | char tmpbuf[TMPBUFLEN]; | 350 | char tmpbuf[TMPBUFLEN]; |
322 | ssize_t length; | 351 | ssize_t length; |
323 | 352 | ||
324 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", | 353 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
325 | security_mls_enabled()); | 354 | security_mls_enabled(fsi->state)); |
326 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 355 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
327 | } | 356 | } |
328 | 357 | ||
@@ -338,20 +367,23 @@ struct policy_load_memory { | |||
338 | 367 | ||
339 | static int sel_open_policy(struct inode *inode, struct file *filp) | 368 | static int sel_open_policy(struct inode *inode, struct file *filp) |
340 | { | 369 | { |
370 | struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; | ||
371 | struct selinux_state *state = fsi->state; | ||
341 | struct policy_load_memory *plm = NULL; | 372 | struct policy_load_memory *plm = NULL; |
342 | int rc; | 373 | int rc; |
343 | 374 | ||
344 | BUG_ON(filp->private_data); | 375 | BUG_ON(filp->private_data); |
345 | 376 | ||
346 | mutex_lock(&sel_mutex); | 377 | mutex_lock(&fsi->mutex); |
347 | 378 | ||
348 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 379 | rc = avc_has_perm(&selinux_state, |
380 | current_sid(), SECINITSID_SECURITY, | ||
349 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | 381 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); |
350 | if (rc) | 382 | if (rc) |
351 | goto err; | 383 | goto err; |
352 | 384 | ||
353 | rc = -EBUSY; | 385 | rc = -EBUSY; |
354 | if (policy_opened) | 386 | if (fsi->policy_opened) |
355 | goto err; | 387 | goto err; |
356 | 388 | ||
357 | rc = -ENOMEM; | 389 | rc = -ENOMEM; |
@@ -359,25 +391,25 @@ static int sel_open_policy(struct inode *inode, struct file *filp) | |||
359 | if (!plm) | 391 | if (!plm) |
360 | goto err; | 392 | goto err; |
361 | 393 | ||
362 | if (i_size_read(inode) != security_policydb_len()) { | 394 | if (i_size_read(inode) != security_policydb_len(state)) { |
363 | inode_lock(inode); | 395 | inode_lock(inode); |
364 | i_size_write(inode, security_policydb_len()); | 396 | i_size_write(inode, security_policydb_len(state)); |
365 | inode_unlock(inode); | 397 | inode_unlock(inode); |
366 | } | 398 | } |
367 | 399 | ||
368 | rc = security_read_policy(&plm->data, &plm->len); | 400 | rc = security_read_policy(state, &plm->data, &plm->len); |
369 | if (rc) | 401 | if (rc) |
370 | goto err; | 402 | goto err; |
371 | 403 | ||
372 | policy_opened = 1; | 404 | fsi->policy_opened = 1; |
373 | 405 | ||
374 | filp->private_data = plm; | 406 | filp->private_data = plm; |
375 | 407 | ||
376 | mutex_unlock(&sel_mutex); | 408 | mutex_unlock(&fsi->mutex); |
377 | 409 | ||
378 | return 0; | 410 | return 0; |
379 | err: | 411 | err: |
380 | mutex_unlock(&sel_mutex); | 412 | mutex_unlock(&fsi->mutex); |
381 | 413 | ||
382 | if (plm) | 414 | if (plm) |
383 | vfree(plm->data); | 415 | vfree(plm->data); |
@@ -387,11 +419,12 @@ err: | |||
387 | 419 | ||
388 | static int sel_release_policy(struct inode *inode, struct file *filp) | 420 | static int sel_release_policy(struct inode *inode, struct file *filp) |
389 | { | 421 | { |
422 | struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; | ||
390 | struct policy_load_memory *plm = filp->private_data; | 423 | struct policy_load_memory *plm = filp->private_data; |
391 | 424 | ||
392 | BUG_ON(!plm); | 425 | BUG_ON(!plm); |
393 | 426 | ||
394 | policy_opened = 0; | 427 | fsi->policy_opened = 0; |
395 | 428 | ||
396 | vfree(plm->data); | 429 | vfree(plm->data); |
397 | kfree(plm); | 430 | kfree(plm); |
@@ -402,19 +435,21 @@ static int sel_release_policy(struct inode *inode, struct file *filp) | |||
402 | static ssize_t sel_read_policy(struct file *filp, char __user *buf, | 435 | static ssize_t sel_read_policy(struct file *filp, char __user *buf, |
403 | size_t count, loff_t *ppos) | 436 | size_t count, loff_t *ppos) |
404 | { | 437 | { |
438 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
405 | struct policy_load_memory *plm = filp->private_data; | 439 | struct policy_load_memory *plm = filp->private_data; |
406 | int ret; | 440 | int ret; |
407 | 441 | ||
408 | mutex_lock(&sel_mutex); | 442 | mutex_lock(&fsi->mutex); |
409 | 443 | ||
410 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 444 | ret = avc_has_perm(&selinux_state, |
445 | current_sid(), SECINITSID_SECURITY, | ||
411 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | 446 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); |
412 | if (ret) | 447 | if (ret) |
413 | goto out; | 448 | goto out; |
414 | 449 | ||
415 | ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); | 450 | ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); |
416 | out: | 451 | out: |
417 | mutex_unlock(&sel_mutex); | 452 | mutex_unlock(&fsi->mutex); |
418 | return ret; | 453 | return ret; |
419 | } | 454 | } |
420 | 455 | ||
@@ -468,16 +503,43 @@ static const struct file_operations sel_policy_ops = { | |||
468 | .llseek = generic_file_llseek, | 503 | .llseek = generic_file_llseek, |
469 | }; | 504 | }; |
470 | 505 | ||
506 | static int sel_make_policy_nodes(struct selinux_fs_info *fsi) | ||
507 | { | ||
508 | int ret; | ||
509 | |||
510 | ret = sel_make_bools(fsi); | ||
511 | if (ret) { | ||
512 | pr_err("SELinux: failed to load policy booleans\n"); | ||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | ret = sel_make_classes(fsi); | ||
517 | if (ret) { | ||
518 | pr_err("SELinux: failed to load policy classes\n"); | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | ret = sel_make_policycap(fsi); | ||
523 | if (ret) { | ||
524 | pr_err("SELinux: failed to load policy capabilities\n"); | ||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
471 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 531 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
472 | size_t count, loff_t *ppos) | 532 | size_t count, loff_t *ppos) |
473 | 533 | ||
474 | { | 534 | { |
535 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
475 | ssize_t length; | 536 | ssize_t length; |
476 | void *data = NULL; | 537 | void *data = NULL; |
477 | 538 | ||
478 | mutex_lock(&sel_mutex); | 539 | mutex_lock(&fsi->mutex); |
479 | 540 | ||
480 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 541 | length = avc_has_perm(&selinux_state, |
542 | current_sid(), SECINITSID_SECURITY, | ||
481 | SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); | 543 | SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); |
482 | if (length) | 544 | if (length) |
483 | goto out; | 545 | goto out; |
@@ -500,29 +562,15 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
500 | if (copy_from_user(data, buf, count) != 0) | 562 | if (copy_from_user(data, buf, count) != 0) |
501 | goto out; | 563 | goto out; |
502 | 564 | ||
503 | length = security_load_policy(data, count); | 565 | length = security_load_policy(fsi->state, data, count); |
504 | if (length) { | 566 | if (length) { |
505 | pr_warn_ratelimited("SELinux: failed to load policy\n"); | 567 | pr_warn_ratelimited("SELinux: failed to load policy\n"); |
506 | goto out; | 568 | goto out; |
507 | } | 569 | } |
508 | 570 | ||
509 | length = sel_make_bools(); | 571 | length = sel_make_policy_nodes(fsi); |
510 | if (length) { | 572 | if (length) |
511 | pr_err("SELinux: failed to load policy booleans\n"); | ||
512 | goto out1; | ||
513 | } | ||
514 | |||
515 | length = sel_make_classes(); | ||
516 | if (length) { | ||
517 | pr_err("SELinux: failed to load policy classes\n"); | ||
518 | goto out1; | ||
519 | } | ||
520 | |||
521 | length = sel_make_policycap(); | ||
522 | if (length) { | ||
523 | pr_err("SELinux: failed to load policy capabilities\n"); | ||
524 | goto out1; | 573 | goto out1; |
525 | } | ||
526 | 574 | ||
527 | length = count; | 575 | length = count; |
528 | 576 | ||
@@ -532,7 +580,7 @@ out1: | |||
532 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 580 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
533 | audit_get_sessionid(current)); | 581 | audit_get_sessionid(current)); |
534 | out: | 582 | out: |
535 | mutex_unlock(&sel_mutex); | 583 | mutex_unlock(&fsi->mutex); |
536 | vfree(data); | 584 | vfree(data); |
537 | return length; | 585 | return length; |
538 | } | 586 | } |
@@ -544,20 +592,23 @@ static const struct file_operations sel_load_ops = { | |||
544 | 592 | ||
545 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | 593 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) |
546 | { | 594 | { |
595 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
596 | struct selinux_state *state = fsi->state; | ||
547 | char *canon = NULL; | 597 | char *canon = NULL; |
548 | u32 sid, len; | 598 | u32 sid, len; |
549 | ssize_t length; | 599 | ssize_t length; |
550 | 600 | ||
551 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 601 | length = avc_has_perm(&selinux_state, |
602 | current_sid(), SECINITSID_SECURITY, | ||
552 | SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); | 603 | SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); |
553 | if (length) | 604 | if (length) |
554 | goto out; | 605 | goto out; |
555 | 606 | ||
556 | length = security_context_to_sid(buf, size, &sid, GFP_KERNEL); | 607 | length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL); |
557 | if (length) | 608 | if (length) |
558 | goto out; | 609 | goto out; |
559 | 610 | ||
560 | length = security_sid_to_context(sid, &canon, &len); | 611 | length = security_sid_to_context(state, sid, &canon, &len); |
561 | if (length) | 612 | if (length) |
562 | goto out; | 613 | goto out; |
563 | 614 | ||
@@ -578,21 +629,24 @@ out: | |||
578 | static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, | 629 | static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, |
579 | size_t count, loff_t *ppos) | 630 | size_t count, loff_t *ppos) |
580 | { | 631 | { |
632 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
581 | char tmpbuf[TMPBUFLEN]; | 633 | char tmpbuf[TMPBUFLEN]; |
582 | ssize_t length; | 634 | ssize_t length; |
583 | 635 | ||
584 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_checkreqprot); | 636 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", fsi->state->checkreqprot); |
585 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 637 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
586 | } | 638 | } |
587 | 639 | ||
588 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | 640 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, |
589 | size_t count, loff_t *ppos) | 641 | size_t count, loff_t *ppos) |
590 | { | 642 | { |
643 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
591 | char *page; | 644 | char *page; |
592 | ssize_t length; | 645 | ssize_t length; |
593 | unsigned int new_value; | 646 | unsigned int new_value; |
594 | 647 | ||
595 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 648 | length = avc_has_perm(&selinux_state, |
649 | current_sid(), SECINITSID_SECURITY, | ||
596 | SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, | 650 | SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, |
597 | NULL); | 651 | NULL); |
598 | if (length) | 652 | if (length) |
@@ -613,7 +667,7 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | |||
613 | if (sscanf(page, "%u", &new_value) != 1) | 667 | if (sscanf(page, "%u", &new_value) != 1) |
614 | goto out; | 668 | goto out; |
615 | 669 | ||
616 | selinux_checkreqprot = new_value ? 1 : 0; | 670 | fsi->state->checkreqprot = new_value ? 1 : 0; |
617 | length = count; | 671 | length = count; |
618 | out: | 672 | out: |
619 | kfree(page); | 673 | kfree(page); |
@@ -629,13 +683,16 @@ static ssize_t sel_write_validatetrans(struct file *file, | |||
629 | const char __user *buf, | 683 | const char __user *buf, |
630 | size_t count, loff_t *ppos) | 684 | size_t count, loff_t *ppos) |
631 | { | 685 | { |
686 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
687 | struct selinux_state *state = fsi->state; | ||
632 | char *oldcon = NULL, *newcon = NULL, *taskcon = NULL; | 688 | char *oldcon = NULL, *newcon = NULL, *taskcon = NULL; |
633 | char *req = NULL; | 689 | char *req = NULL; |
634 | u32 osid, nsid, tsid; | 690 | u32 osid, nsid, tsid; |
635 | u16 tclass; | 691 | u16 tclass; |
636 | int rc; | 692 | int rc; |
637 | 693 | ||
638 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 694 | rc = avc_has_perm(&selinux_state, |
695 | current_sid(), SECINITSID_SECURITY, | ||
639 | SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); | 696 | SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); |
640 | if (rc) | 697 | if (rc) |
641 | goto out; | 698 | goto out; |
@@ -673,19 +730,19 @@ static ssize_t sel_write_validatetrans(struct file *file, | |||
673 | if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) | 730 | if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) |
674 | goto out; | 731 | goto out; |
675 | 732 | ||
676 | rc = security_context_str_to_sid(oldcon, &osid, GFP_KERNEL); | 733 | rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL); |
677 | if (rc) | 734 | if (rc) |
678 | goto out; | 735 | goto out; |
679 | 736 | ||
680 | rc = security_context_str_to_sid(newcon, &nsid, GFP_KERNEL); | 737 | rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL); |
681 | if (rc) | 738 | if (rc) |
682 | goto out; | 739 | goto out; |
683 | 740 | ||
684 | rc = security_context_str_to_sid(taskcon, &tsid, GFP_KERNEL); | 741 | rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL); |
685 | if (rc) | 742 | if (rc) |
686 | goto out; | 743 | goto out; |
687 | 744 | ||
688 | rc = security_validate_transition_user(osid, nsid, tsid, tclass); | 745 | rc = security_validate_transition_user(state, osid, nsid, tsid, tclass); |
689 | if (!rc) | 746 | if (!rc) |
690 | rc = count; | 747 | rc = count; |
691 | out: | 748 | out: |
@@ -755,13 +812,16 @@ static const struct file_operations transaction_ops = { | |||
755 | 812 | ||
756 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | 813 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) |
757 | { | 814 | { |
815 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
816 | struct selinux_state *state = fsi->state; | ||
758 | char *scon = NULL, *tcon = NULL; | 817 | char *scon = NULL, *tcon = NULL; |
759 | u32 ssid, tsid; | 818 | u32 ssid, tsid; |
760 | u16 tclass; | 819 | u16 tclass; |
761 | struct av_decision avd; | 820 | struct av_decision avd; |
762 | ssize_t length; | 821 | ssize_t length; |
763 | 822 | ||
764 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 823 | length = avc_has_perm(&selinux_state, |
824 | current_sid(), SECINITSID_SECURITY, | ||
765 | SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); | 825 | SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); |
766 | if (length) | 826 | if (length) |
767 | goto out; | 827 | goto out; |
@@ -780,15 +840,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
780 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 840 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
781 | goto out; | 841 | goto out; |
782 | 842 | ||
783 | length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); | 843 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
784 | if (length) | 844 | if (length) |
785 | goto out; | 845 | goto out; |
786 | 846 | ||
787 | length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); | 847 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
788 | if (length) | 848 | if (length) |
789 | goto out; | 849 | goto out; |
790 | 850 | ||
791 | security_compute_av_user(ssid, tsid, tclass, &avd); | 851 | security_compute_av_user(state, ssid, tsid, tclass, &avd); |
792 | 852 | ||
793 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 853 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
794 | "%x %x %x %x %u %x", | 854 | "%x %x %x %x %u %x", |
@@ -803,6 +863,8 @@ out: | |||
803 | 863 | ||
804 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | 864 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) |
805 | { | 865 | { |
866 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
867 | struct selinux_state *state = fsi->state; | ||
806 | char *scon = NULL, *tcon = NULL; | 868 | char *scon = NULL, *tcon = NULL; |
807 | char *namebuf = NULL, *objname = NULL; | 869 | char *namebuf = NULL, *objname = NULL; |
808 | u32 ssid, tsid, newsid; | 870 | u32 ssid, tsid, newsid; |
@@ -812,7 +874,8 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
812 | u32 len; | 874 | u32 len; |
813 | int nargs; | 875 | int nargs; |
814 | 876 | ||
815 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 877 | length = avc_has_perm(&selinux_state, |
878 | current_sid(), SECINITSID_SECURITY, | ||
816 | SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, | 879 | SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, |
817 | NULL); | 880 | NULL); |
818 | if (length) | 881 | if (length) |
@@ -868,20 +931,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
868 | objname = namebuf; | 931 | objname = namebuf; |
869 | } | 932 | } |
870 | 933 | ||
871 | length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); | 934 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
872 | if (length) | 935 | if (length) |
873 | goto out; | 936 | goto out; |
874 | 937 | ||
875 | length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); | 938 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
876 | if (length) | 939 | if (length) |
877 | goto out; | 940 | goto out; |
878 | 941 | ||
879 | length = security_transition_sid_user(ssid, tsid, tclass, | 942 | length = security_transition_sid_user(state, ssid, tsid, tclass, |
880 | objname, &newsid); | 943 | objname, &newsid); |
881 | if (length) | 944 | if (length) |
882 | goto out; | 945 | goto out; |
883 | 946 | ||
884 | length = security_sid_to_context(newsid, &newcon, &len); | 947 | length = security_sid_to_context(state, newsid, &newcon, &len); |
885 | if (length) | 948 | if (length) |
886 | goto out; | 949 | goto out; |
887 | 950 | ||
@@ -904,6 +967,8 @@ out: | |||
904 | 967 | ||
905 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | 968 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) |
906 | { | 969 | { |
970 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
971 | struct selinux_state *state = fsi->state; | ||
907 | char *scon = NULL, *tcon = NULL; | 972 | char *scon = NULL, *tcon = NULL; |
908 | u32 ssid, tsid, newsid; | 973 | u32 ssid, tsid, newsid; |
909 | u16 tclass; | 974 | u16 tclass; |
@@ -911,7 +976,8 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
911 | char *newcon = NULL; | 976 | char *newcon = NULL; |
912 | u32 len; | 977 | u32 len; |
913 | 978 | ||
914 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 979 | length = avc_has_perm(&selinux_state, |
980 | current_sid(), SECINITSID_SECURITY, | ||
915 | SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, | 981 | SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, |
916 | NULL); | 982 | NULL); |
917 | if (length) | 983 | if (length) |
@@ -931,19 +997,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
931 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 997 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
932 | goto out; | 998 | goto out; |
933 | 999 | ||
934 | length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); | 1000 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
935 | if (length) | 1001 | if (length) |
936 | goto out; | 1002 | goto out; |
937 | 1003 | ||
938 | length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); | 1004 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
939 | if (length) | 1005 | if (length) |
940 | goto out; | 1006 | goto out; |
941 | 1007 | ||
942 | length = security_change_sid(ssid, tsid, tclass, &newsid); | 1008 | length = security_change_sid(state, ssid, tsid, tclass, &newsid); |
943 | if (length) | 1009 | if (length) |
944 | goto out; | 1010 | goto out; |
945 | 1011 | ||
946 | length = security_sid_to_context(newsid, &newcon, &len); | 1012 | length = security_sid_to_context(state, newsid, &newcon, &len); |
947 | if (length) | 1013 | if (length) |
948 | goto out; | 1014 | goto out; |
949 | 1015 | ||
@@ -962,6 +1028,8 @@ out: | |||
962 | 1028 | ||
963 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | 1029 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) |
964 | { | 1030 | { |
1031 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1032 | struct selinux_state *state = fsi->state; | ||
965 | char *con = NULL, *user = NULL, *ptr; | 1033 | char *con = NULL, *user = NULL, *ptr; |
966 | u32 sid, *sids = NULL; | 1034 | u32 sid, *sids = NULL; |
967 | ssize_t length; | 1035 | ssize_t length; |
@@ -969,7 +1037,8 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
969 | int i, rc; | 1037 | int i, rc; |
970 | u32 len, nsids; | 1038 | u32 len, nsids; |
971 | 1039 | ||
972 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1040 | length = avc_has_perm(&selinux_state, |
1041 | current_sid(), SECINITSID_SECURITY, | ||
973 | SECCLASS_SECURITY, SECURITY__COMPUTE_USER, | 1042 | SECCLASS_SECURITY, SECURITY__COMPUTE_USER, |
974 | NULL); | 1043 | NULL); |
975 | if (length) | 1044 | if (length) |
@@ -989,18 +1058,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
989 | if (sscanf(buf, "%s %s", con, user) != 2) | 1058 | if (sscanf(buf, "%s %s", con, user) != 2) |
990 | goto out; | 1059 | goto out; |
991 | 1060 | ||
992 | length = security_context_str_to_sid(con, &sid, GFP_KERNEL); | 1061 | length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL); |
993 | if (length) | 1062 | if (length) |
994 | goto out; | 1063 | goto out; |
995 | 1064 | ||
996 | length = security_get_user_sids(sid, user, &sids, &nsids); | 1065 | length = security_get_user_sids(state, sid, user, &sids, &nsids); |
997 | if (length) | 1066 | if (length) |
998 | goto out; | 1067 | goto out; |
999 | 1068 | ||
1000 | length = sprintf(buf, "%u", nsids) + 1; | 1069 | length = sprintf(buf, "%u", nsids) + 1; |
1001 | ptr = buf + length; | 1070 | ptr = buf + length; |
1002 | for (i = 0; i < nsids; i++) { | 1071 | for (i = 0; i < nsids; i++) { |
1003 | rc = security_sid_to_context(sids[i], &newcon, &len); | 1072 | rc = security_sid_to_context(state, sids[i], &newcon, &len); |
1004 | if (rc) { | 1073 | if (rc) { |
1005 | length = rc; | 1074 | length = rc; |
1006 | goto out; | 1075 | goto out; |
@@ -1024,6 +1093,8 @@ out: | |||
1024 | 1093 | ||
1025 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | 1094 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) |
1026 | { | 1095 | { |
1096 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1097 | struct selinux_state *state = fsi->state; | ||
1027 | char *scon = NULL, *tcon = NULL; | 1098 | char *scon = NULL, *tcon = NULL; |
1028 | u32 ssid, tsid, newsid; | 1099 | u32 ssid, tsid, newsid; |
1029 | u16 tclass; | 1100 | u16 tclass; |
@@ -1031,7 +1102,8 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
1031 | char *newcon = NULL; | 1102 | char *newcon = NULL; |
1032 | u32 len; | 1103 | u32 len; |
1033 | 1104 | ||
1034 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1105 | length = avc_has_perm(&selinux_state, |
1106 | current_sid(), SECINITSID_SECURITY, | ||
1035 | SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, | 1107 | SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, |
1036 | NULL); | 1108 | NULL); |
1037 | if (length) | 1109 | if (length) |
@@ -1051,19 +1123,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
1051 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 1123 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
1052 | goto out; | 1124 | goto out; |
1053 | 1125 | ||
1054 | length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); | 1126 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
1055 | if (length) | 1127 | if (length) |
1056 | goto out; | 1128 | goto out; |
1057 | 1129 | ||
1058 | length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); | 1130 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
1059 | if (length) | 1131 | if (length) |
1060 | goto out; | 1132 | goto out; |
1061 | 1133 | ||
1062 | length = security_member_sid(ssid, tsid, tclass, &newsid); | 1134 | length = security_member_sid(state, ssid, tsid, tclass, &newsid); |
1063 | if (length) | 1135 | if (length) |
1064 | goto out; | 1136 | goto out; |
1065 | 1137 | ||
1066 | length = security_sid_to_context(newsid, &newcon, &len); | 1138 | length = security_sid_to_context(state, newsid, &newcon, &len); |
1067 | if (length) | 1139 | if (length) |
1068 | goto out; | 1140 | goto out; |
1069 | 1141 | ||
@@ -1097,6 +1169,7 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) | |||
1097 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, | 1169 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, |
1098 | size_t count, loff_t *ppos) | 1170 | size_t count, loff_t *ppos) |
1099 | { | 1171 | { |
1172 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1100 | char *page = NULL; | 1173 | char *page = NULL; |
1101 | ssize_t length; | 1174 | ssize_t length; |
1102 | ssize_t ret; | 1175 | ssize_t ret; |
@@ -1104,10 +1177,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1104 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; | 1177 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; |
1105 | const char *name = filep->f_path.dentry->d_name.name; | 1178 | const char *name = filep->f_path.dentry->d_name.name; |
1106 | 1179 | ||
1107 | mutex_lock(&sel_mutex); | 1180 | mutex_lock(&fsi->mutex); |
1108 | 1181 | ||
1109 | ret = -EINVAL; | 1182 | ret = -EINVAL; |
1110 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) | 1183 | if (index >= fsi->bool_num || strcmp(name, |
1184 | fsi->bool_pending_names[index])) | ||
1111 | goto out; | 1185 | goto out; |
1112 | 1186 | ||
1113 | ret = -ENOMEM; | 1187 | ret = -ENOMEM; |
@@ -1115,16 +1189,16 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1115 | if (!page) | 1189 | if (!page) |
1116 | goto out; | 1190 | goto out; |
1117 | 1191 | ||
1118 | cur_enforcing = security_get_bool_value(index); | 1192 | cur_enforcing = security_get_bool_value(fsi->state, index); |
1119 | if (cur_enforcing < 0) { | 1193 | if (cur_enforcing < 0) { |
1120 | ret = cur_enforcing; | 1194 | ret = cur_enforcing; |
1121 | goto out; | 1195 | goto out; |
1122 | } | 1196 | } |
1123 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, | 1197 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, |
1124 | bool_pending_values[index]); | 1198 | fsi->bool_pending_values[index]); |
1125 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 1199 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
1126 | out: | 1200 | out: |
1127 | mutex_unlock(&sel_mutex); | 1201 | mutex_unlock(&fsi->mutex); |
1128 | free_page((unsigned long)page); | 1202 | free_page((unsigned long)page); |
1129 | return ret; | 1203 | return ret; |
1130 | } | 1204 | } |
@@ -1132,22 +1206,25 @@ out: | |||
1132 | static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | 1206 | static ssize_t sel_write_bool(struct file *filep, const char __user *buf, |
1133 | size_t count, loff_t *ppos) | 1207 | size_t count, loff_t *ppos) |
1134 | { | 1208 | { |
1209 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1135 | char *page = NULL; | 1210 | char *page = NULL; |
1136 | ssize_t length; | 1211 | ssize_t length; |
1137 | int new_value; | 1212 | int new_value; |
1138 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; | 1213 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; |
1139 | const char *name = filep->f_path.dentry->d_name.name; | 1214 | const char *name = filep->f_path.dentry->d_name.name; |
1140 | 1215 | ||
1141 | mutex_lock(&sel_mutex); | 1216 | mutex_lock(&fsi->mutex); |
1142 | 1217 | ||
1143 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1218 | length = avc_has_perm(&selinux_state, |
1219 | current_sid(), SECINITSID_SECURITY, | ||
1144 | SECCLASS_SECURITY, SECURITY__SETBOOL, | 1220 | SECCLASS_SECURITY, SECURITY__SETBOOL, |
1145 | NULL); | 1221 | NULL); |
1146 | if (length) | 1222 | if (length) |
1147 | goto out; | 1223 | goto out; |
1148 | 1224 | ||
1149 | length = -EINVAL; | 1225 | length = -EINVAL; |
1150 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) | 1226 | if (index >= fsi->bool_num || strcmp(name, |
1227 | fsi->bool_pending_names[index])) | ||
1151 | goto out; | 1228 | goto out; |
1152 | 1229 | ||
1153 | length = -ENOMEM; | 1230 | length = -ENOMEM; |
@@ -1173,11 +1250,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1173 | if (new_value) | 1250 | if (new_value) |
1174 | new_value = 1; | 1251 | new_value = 1; |
1175 | 1252 | ||
1176 | bool_pending_values[index] = new_value; | 1253 | fsi->bool_pending_values[index] = new_value; |
1177 | length = count; | 1254 | length = count; |
1178 | 1255 | ||
1179 | out: | 1256 | out: |
1180 | mutex_unlock(&sel_mutex); | 1257 | mutex_unlock(&fsi->mutex); |
1181 | kfree(page); | 1258 | kfree(page); |
1182 | return length; | 1259 | return length; |
1183 | } | 1260 | } |
@@ -1192,13 +1269,15 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1192 | const char __user *buf, | 1269 | const char __user *buf, |
1193 | size_t count, loff_t *ppos) | 1270 | size_t count, loff_t *ppos) |
1194 | { | 1271 | { |
1272 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1195 | char *page = NULL; | 1273 | char *page = NULL; |
1196 | ssize_t length; | 1274 | ssize_t length; |
1197 | int new_value; | 1275 | int new_value; |
1198 | 1276 | ||
1199 | mutex_lock(&sel_mutex); | 1277 | mutex_lock(&fsi->mutex); |
1200 | 1278 | ||
1201 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1279 | length = avc_has_perm(&selinux_state, |
1280 | current_sid(), SECINITSID_SECURITY, | ||
1202 | SECCLASS_SECURITY, SECURITY__SETBOOL, | 1281 | SECCLASS_SECURITY, SECURITY__SETBOOL, |
1203 | NULL); | 1282 | NULL); |
1204 | if (length) | 1283 | if (length) |
@@ -1225,14 +1304,15 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1225 | goto out; | 1304 | goto out; |
1226 | 1305 | ||
1227 | length = 0; | 1306 | length = 0; |
1228 | if (new_value && bool_pending_values) | 1307 | if (new_value && fsi->bool_pending_values) |
1229 | length = security_set_bools(bool_num, bool_pending_values); | 1308 | length = security_set_bools(fsi->state, fsi->bool_num, |
1309 | fsi->bool_pending_values); | ||
1230 | 1310 | ||
1231 | if (!length) | 1311 | if (!length) |
1232 | length = count; | 1312 | length = count; |
1233 | 1313 | ||
1234 | out: | 1314 | out: |
1235 | mutex_unlock(&sel_mutex); | 1315 | mutex_unlock(&fsi->mutex); |
1236 | kfree(page); | 1316 | kfree(page); |
1237 | return length; | 1317 | return length; |
1238 | } | 1318 | } |
@@ -1250,12 +1330,12 @@ static void sel_remove_entries(struct dentry *de) | |||
1250 | 1330 | ||
1251 | #define BOOL_DIR_NAME "booleans" | 1331 | #define BOOL_DIR_NAME "booleans" |
1252 | 1332 | ||
1253 | static int sel_make_bools(void) | 1333 | static int sel_make_bools(struct selinux_fs_info *fsi) |
1254 | { | 1334 | { |
1255 | int i, ret; | 1335 | int i, ret; |
1256 | ssize_t len; | 1336 | ssize_t len; |
1257 | struct dentry *dentry = NULL; | 1337 | struct dentry *dentry = NULL; |
1258 | struct dentry *dir = bool_dir; | 1338 | struct dentry *dir = fsi->bool_dir; |
1259 | struct inode *inode = NULL; | 1339 | struct inode *inode = NULL; |
1260 | struct inode_security_struct *isec; | 1340 | struct inode_security_struct *isec; |
1261 | char **names = NULL, *page; | 1341 | char **names = NULL, *page; |
@@ -1264,13 +1344,13 @@ static int sel_make_bools(void) | |||
1264 | u32 sid; | 1344 | u32 sid; |
1265 | 1345 | ||
1266 | /* remove any existing files */ | 1346 | /* remove any existing files */ |
1267 | for (i = 0; i < bool_num; i++) | 1347 | for (i = 0; i < fsi->bool_num; i++) |
1268 | kfree(bool_pending_names[i]); | 1348 | kfree(fsi->bool_pending_names[i]); |
1269 | kfree(bool_pending_names); | 1349 | kfree(fsi->bool_pending_names); |
1270 | kfree(bool_pending_values); | 1350 | kfree(fsi->bool_pending_values); |
1271 | bool_num = 0; | 1351 | fsi->bool_num = 0; |
1272 | bool_pending_names = NULL; | 1352 | fsi->bool_pending_names = NULL; |
1273 | bool_pending_values = NULL; | 1353 | fsi->bool_pending_values = NULL; |
1274 | 1354 | ||
1275 | sel_remove_entries(dir); | 1355 | sel_remove_entries(dir); |
1276 | 1356 | ||
@@ -1279,7 +1359,7 @@ static int sel_make_bools(void) | |||
1279 | if (!page) | 1359 | if (!page) |
1280 | goto out; | 1360 | goto out; |
1281 | 1361 | ||
1282 | ret = security_get_bools(&num, &names, &values); | 1362 | ret = security_get_bools(fsi->state, &num, &names, &values); |
1283 | if (ret) | 1363 | if (ret) |
1284 | goto out; | 1364 | goto out; |
1285 | 1365 | ||
@@ -1300,7 +1380,8 @@ static int sel_make_bools(void) | |||
1300 | goto out; | 1380 | goto out; |
1301 | 1381 | ||
1302 | isec = (struct inode_security_struct *)inode->i_security; | 1382 | isec = (struct inode_security_struct *)inode->i_security; |
1303 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); | 1383 | ret = security_genfs_sid(fsi->state, "selinuxfs", page, |
1384 | SECCLASS_FILE, &sid); | ||
1304 | if (ret) { | 1385 | if (ret) { |
1305 | pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", | 1386 | pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", |
1306 | page); | 1387 | page); |
@@ -1313,9 +1394,9 @@ static int sel_make_bools(void) | |||
1313 | inode->i_ino = i|SEL_BOOL_INO_OFFSET; | 1394 | inode->i_ino = i|SEL_BOOL_INO_OFFSET; |
1314 | d_add(dentry, inode); | 1395 | d_add(dentry, inode); |
1315 | } | 1396 | } |
1316 | bool_num = num; | 1397 | fsi->bool_num = num; |
1317 | bool_pending_names = names; | 1398 | fsi->bool_pending_names = names; |
1318 | bool_pending_values = values; | 1399 | fsi->bool_pending_values = values; |
1319 | 1400 | ||
1320 | free_page((unsigned long)page); | 1401 | free_page((unsigned long)page); |
1321 | return 0; | 1402 | return 0; |
@@ -1333,17 +1414,16 @@ out: | |||
1333 | return ret; | 1414 | return ret; |
1334 | } | 1415 | } |
1335 | 1416 | ||
1336 | #define NULL_FILE_NAME "null" | ||
1337 | |||
1338 | struct path selinux_null; | ||
1339 | |||
1340 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, | 1417 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, |
1341 | size_t count, loff_t *ppos) | 1418 | size_t count, loff_t *ppos) |
1342 | { | 1419 | { |
1420 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
1421 | struct selinux_state *state = fsi->state; | ||
1343 | char tmpbuf[TMPBUFLEN]; | 1422 | char tmpbuf[TMPBUFLEN]; |
1344 | ssize_t length; | 1423 | ssize_t length; |
1345 | 1424 | ||
1346 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", avc_cache_threshold); | 1425 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", |
1426 | avc_get_cache_threshold(state->avc)); | ||
1347 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 1427 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
1348 | } | 1428 | } |
1349 | 1429 | ||
@@ -1352,11 +1432,14 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
1352 | size_t count, loff_t *ppos) | 1432 | size_t count, loff_t *ppos) |
1353 | 1433 | ||
1354 | { | 1434 | { |
1435 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1436 | struct selinux_state *state = fsi->state; | ||
1355 | char *page; | 1437 | char *page; |
1356 | ssize_t ret; | 1438 | ssize_t ret; |
1357 | unsigned int new_value; | 1439 | unsigned int new_value; |
1358 | 1440 | ||
1359 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1441 | ret = avc_has_perm(&selinux_state, |
1442 | current_sid(), SECINITSID_SECURITY, | ||
1360 | SECCLASS_SECURITY, SECURITY__SETSECPARAM, | 1443 | SECCLASS_SECURITY, SECURITY__SETSECPARAM, |
1361 | NULL); | 1444 | NULL); |
1362 | if (ret) | 1445 | if (ret) |
@@ -1377,7 +1460,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
1377 | if (sscanf(page, "%u", &new_value) != 1) | 1460 | if (sscanf(page, "%u", &new_value) != 1) |
1378 | goto out; | 1461 | goto out; |
1379 | 1462 | ||
1380 | avc_cache_threshold = new_value; | 1463 | avc_set_cache_threshold(state->avc, new_value); |
1381 | 1464 | ||
1382 | ret = count; | 1465 | ret = count; |
1383 | out: | 1466 | out: |
@@ -1388,6 +1471,8 @@ out: | |||
1388 | static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, | 1471 | static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, |
1389 | size_t count, loff_t *ppos) | 1472 | size_t count, loff_t *ppos) |
1390 | { | 1473 | { |
1474 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
1475 | struct selinux_state *state = fsi->state; | ||
1391 | char *page; | 1476 | char *page; |
1392 | ssize_t length; | 1477 | ssize_t length; |
1393 | 1478 | ||
@@ -1395,7 +1480,7 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, | |||
1395 | if (!page) | 1480 | if (!page) |
1396 | return -ENOMEM; | 1481 | return -ENOMEM; |
1397 | 1482 | ||
1398 | length = avc_get_hash_stats(page); | 1483 | length = avc_get_hash_stats(state->avc, page); |
1399 | if (length >= 0) | 1484 | if (length >= 0) |
1400 | length = simple_read_from_buffer(buf, count, ppos, page, length); | 1485 | length = simple_read_from_buffer(buf, count, ppos, page, length); |
1401 | free_page((unsigned long)page); | 1486 | free_page((unsigned long)page); |
@@ -1486,6 +1571,8 @@ static const struct file_operations sel_avc_cache_stats_ops = { | |||
1486 | 1571 | ||
1487 | static int sel_make_avc_files(struct dentry *dir) | 1572 | static int sel_make_avc_files(struct dentry *dir) |
1488 | { | 1573 | { |
1574 | struct super_block *sb = dir->d_sb; | ||
1575 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
1489 | int i; | 1576 | int i; |
1490 | static const struct tree_descr files[] = { | 1577 | static const struct tree_descr files[] = { |
1491 | { "cache_threshold", | 1578 | { "cache_threshold", |
@@ -1509,7 +1596,7 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1509 | return -ENOMEM; | 1596 | return -ENOMEM; |
1510 | 1597 | ||
1511 | inode->i_fop = files[i].ops; | 1598 | inode->i_fop = files[i].ops; |
1512 | inode->i_ino = ++sel_last_ino; | 1599 | inode->i_ino = ++fsi->last_ino; |
1513 | d_add(dentry, inode); | 1600 | d_add(dentry, inode); |
1514 | } | 1601 | } |
1515 | 1602 | ||
@@ -1519,12 +1606,13 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1519 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, | 1606 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, |
1520 | size_t count, loff_t *ppos) | 1607 | size_t count, loff_t *ppos) |
1521 | { | 1608 | { |
1609 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1522 | char *con; | 1610 | char *con; |
1523 | u32 sid, len; | 1611 | u32 sid, len; |
1524 | ssize_t ret; | 1612 | ssize_t ret; |
1525 | 1613 | ||
1526 | sid = file_inode(file)->i_ino&SEL_INO_MASK; | 1614 | sid = file_inode(file)->i_ino&SEL_INO_MASK; |
1527 | ret = security_sid_to_context(sid, &con, &len); | 1615 | ret = security_sid_to_context(fsi->state, sid, &con, &len); |
1528 | if (ret) | 1616 | if (ret) |
1529 | return ret; | 1617 | return ret; |
1530 | 1618 | ||
@@ -1612,12 +1700,13 @@ static const struct file_operations sel_perm_ops = { | |||
1612 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, | 1700 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, |
1613 | size_t count, loff_t *ppos) | 1701 | size_t count, loff_t *ppos) |
1614 | { | 1702 | { |
1703 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1615 | int value; | 1704 | int value; |
1616 | char tmpbuf[TMPBUFLEN]; | 1705 | char tmpbuf[TMPBUFLEN]; |
1617 | ssize_t length; | 1706 | ssize_t length; |
1618 | unsigned long i_ino = file_inode(file)->i_ino; | 1707 | unsigned long i_ino = file_inode(file)->i_ino; |
1619 | 1708 | ||
1620 | value = security_policycap_supported(i_ino & SEL_INO_MASK); | 1709 | value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK); |
1621 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); | 1710 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); |
1622 | 1711 | ||
1623 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 1712 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
@@ -1631,10 +1720,11 @@ static const struct file_operations sel_policycap_ops = { | |||
1631 | static int sel_make_perm_files(char *objclass, int classvalue, | 1720 | static int sel_make_perm_files(char *objclass, int classvalue, |
1632 | struct dentry *dir) | 1721 | struct dentry *dir) |
1633 | { | 1722 | { |
1723 | struct selinux_fs_info *fsi = dir->d_sb->s_fs_info; | ||
1634 | int i, rc, nperms; | 1724 | int i, rc, nperms; |
1635 | char **perms; | 1725 | char **perms; |
1636 | 1726 | ||
1637 | rc = security_get_permissions(objclass, &perms, &nperms); | 1727 | rc = security_get_permissions(fsi->state, objclass, &perms, &nperms); |
1638 | if (rc) | 1728 | if (rc) |
1639 | return rc; | 1729 | return rc; |
1640 | 1730 | ||
@@ -1668,6 +1758,8 @@ out: | |||
1668 | static int sel_make_class_dir_entries(char *classname, int index, | 1758 | static int sel_make_class_dir_entries(char *classname, int index, |
1669 | struct dentry *dir) | 1759 | struct dentry *dir) |
1670 | { | 1760 | { |
1761 | struct super_block *sb = dir->d_sb; | ||
1762 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
1671 | struct dentry *dentry = NULL; | 1763 | struct dentry *dentry = NULL; |
1672 | struct inode *inode = NULL; | 1764 | struct inode *inode = NULL; |
1673 | int rc; | 1765 | int rc; |
@@ -1684,7 +1776,7 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1684 | inode->i_ino = sel_class_to_ino(index); | 1776 | inode->i_ino = sel_class_to_ino(index); |
1685 | d_add(dentry, inode); | 1777 | d_add(dentry, inode); |
1686 | 1778 | ||
1687 | dentry = sel_make_dir(dir, "perms", &last_class_ino); | 1779 | dentry = sel_make_dir(dir, "perms", &fsi->last_class_ino); |
1688 | if (IS_ERR(dentry)) | 1780 | if (IS_ERR(dentry)) |
1689 | return PTR_ERR(dentry); | 1781 | return PTR_ERR(dentry); |
1690 | 1782 | ||
@@ -1693,26 +1785,27 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1693 | return rc; | 1785 | return rc; |
1694 | } | 1786 | } |
1695 | 1787 | ||
1696 | static int sel_make_classes(void) | 1788 | static int sel_make_classes(struct selinux_fs_info *fsi) |
1697 | { | 1789 | { |
1790 | |||
1698 | int rc, nclasses, i; | 1791 | int rc, nclasses, i; |
1699 | char **classes; | 1792 | char **classes; |
1700 | 1793 | ||
1701 | /* delete any existing entries */ | 1794 | /* delete any existing entries */ |
1702 | sel_remove_entries(class_dir); | 1795 | sel_remove_entries(fsi->class_dir); |
1703 | 1796 | ||
1704 | rc = security_get_classes(&classes, &nclasses); | 1797 | rc = security_get_classes(fsi->state, &classes, &nclasses); |
1705 | if (rc) | 1798 | if (rc) |
1706 | return rc; | 1799 | return rc; |
1707 | 1800 | ||
1708 | /* +2 since classes are 1-indexed */ | 1801 | /* +2 since classes are 1-indexed */ |
1709 | last_class_ino = sel_class_to_ino(nclasses + 2); | 1802 | fsi->last_class_ino = sel_class_to_ino(nclasses + 2); |
1710 | 1803 | ||
1711 | for (i = 0; i < nclasses; i++) { | 1804 | for (i = 0; i < nclasses; i++) { |
1712 | struct dentry *class_name_dir; | 1805 | struct dentry *class_name_dir; |
1713 | 1806 | ||
1714 | class_name_dir = sel_make_dir(class_dir, classes[i], | 1807 | class_name_dir = sel_make_dir(fsi->class_dir, classes[i], |
1715 | &last_class_ino); | 1808 | &fsi->last_class_ino); |
1716 | if (IS_ERR(class_name_dir)) { | 1809 | if (IS_ERR(class_name_dir)) { |
1717 | rc = PTR_ERR(class_name_dir); | 1810 | rc = PTR_ERR(class_name_dir); |
1718 | goto out; | 1811 | goto out; |
@@ -1732,25 +1825,25 @@ out: | |||
1732 | return rc; | 1825 | return rc; |
1733 | } | 1826 | } |
1734 | 1827 | ||
1735 | static int sel_make_policycap(void) | 1828 | static int sel_make_policycap(struct selinux_fs_info *fsi) |
1736 | { | 1829 | { |
1737 | unsigned int iter; | 1830 | unsigned int iter; |
1738 | struct dentry *dentry = NULL; | 1831 | struct dentry *dentry = NULL; |
1739 | struct inode *inode = NULL; | 1832 | struct inode *inode = NULL; |
1740 | 1833 | ||
1741 | sel_remove_entries(policycap_dir); | 1834 | sel_remove_entries(fsi->policycap_dir); |
1742 | 1835 | ||
1743 | for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) { | 1836 | for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) { |
1744 | if (iter < ARRAY_SIZE(selinux_policycap_names)) | 1837 | if (iter < ARRAY_SIZE(selinux_policycap_names)) |
1745 | dentry = d_alloc_name(policycap_dir, | 1838 | dentry = d_alloc_name(fsi->policycap_dir, |
1746 | selinux_policycap_names[iter]); | 1839 | selinux_policycap_names[iter]); |
1747 | else | 1840 | else |
1748 | dentry = d_alloc_name(policycap_dir, "unknown"); | 1841 | dentry = d_alloc_name(fsi->policycap_dir, "unknown"); |
1749 | 1842 | ||
1750 | if (dentry == NULL) | 1843 | if (dentry == NULL) |
1751 | return -ENOMEM; | 1844 | return -ENOMEM; |
1752 | 1845 | ||
1753 | inode = sel_make_inode(policycap_dir->d_sb, S_IFREG | S_IRUGO); | 1846 | inode = sel_make_inode(fsi->sb, S_IFREG | 0444); |
1754 | if (inode == NULL) | 1847 | if (inode == NULL) |
1755 | return -ENOMEM; | 1848 | return -ENOMEM; |
1756 | 1849 | ||
@@ -1789,8 +1882,11 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | |||
1789 | return dentry; | 1882 | return dentry; |
1790 | } | 1883 | } |
1791 | 1884 | ||
1885 | #define NULL_FILE_NAME "null" | ||
1886 | |||
1792 | static int sel_fill_super(struct super_block *sb, void *data, int silent) | 1887 | static int sel_fill_super(struct super_block *sb, void *data, int silent) |
1793 | { | 1888 | { |
1889 | struct selinux_fs_info *fsi; | ||
1794 | int ret; | 1890 | int ret; |
1795 | struct dentry *dentry; | 1891 | struct dentry *dentry; |
1796 | struct inode *inode; | 1892 | struct inode *inode; |
@@ -1818,14 +1914,20 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1818 | S_IWUGO}, | 1914 | S_IWUGO}, |
1819 | /* last one */ {""} | 1915 | /* last one */ {""} |
1820 | }; | 1916 | }; |
1917 | |||
1918 | ret = selinux_fs_info_create(sb); | ||
1919 | if (ret) | ||
1920 | goto err; | ||
1921 | |||
1821 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1922 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
1822 | if (ret) | 1923 | if (ret) |
1823 | goto err; | 1924 | goto err; |
1824 | 1925 | ||
1825 | bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &sel_last_ino); | 1926 | fsi = sb->s_fs_info; |
1826 | if (IS_ERR(bool_dir)) { | 1927 | fsi->bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &fsi->last_ino); |
1827 | ret = PTR_ERR(bool_dir); | 1928 | if (IS_ERR(fsi->bool_dir)) { |
1828 | bool_dir = NULL; | 1929 | ret = PTR_ERR(fsi->bool_dir); |
1930 | fsi->bool_dir = NULL; | ||
1829 | goto err; | 1931 | goto err; |
1830 | } | 1932 | } |
1831 | 1933 | ||
@@ -1839,7 +1941,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1839 | if (!inode) | 1941 | if (!inode) |
1840 | goto err; | 1942 | goto err; |
1841 | 1943 | ||
1842 | inode->i_ino = ++sel_last_ino; | 1944 | inode->i_ino = ++fsi->last_ino; |
1843 | isec = (struct inode_security_struct *)inode->i_security; | 1945 | isec = (struct inode_security_struct *)inode->i_security; |
1844 | isec->sid = SECINITSID_DEVNULL; | 1946 | isec->sid = SECINITSID_DEVNULL; |
1845 | isec->sclass = SECCLASS_CHR_FILE; | 1947 | isec->sclass = SECCLASS_CHR_FILE; |
@@ -1847,9 +1949,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1847 | 1949 | ||
1848 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); | 1950 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); |
1849 | d_add(dentry, inode); | 1951 | d_add(dentry, inode); |
1850 | selinux_null.dentry = dentry; | ||
1851 | 1952 | ||
1852 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); | 1953 | dentry = sel_make_dir(sb->s_root, "avc", &fsi->last_ino); |
1853 | if (IS_ERR(dentry)) { | 1954 | if (IS_ERR(dentry)) { |
1854 | ret = PTR_ERR(dentry); | 1955 | ret = PTR_ERR(dentry); |
1855 | goto err; | 1956 | goto err; |
@@ -1859,7 +1960,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1859 | if (ret) | 1960 | if (ret) |
1860 | goto err; | 1961 | goto err; |
1861 | 1962 | ||
1862 | dentry = sel_make_dir(sb->s_root, "initial_contexts", &sel_last_ino); | 1963 | dentry = sel_make_dir(sb->s_root, "initial_contexts", &fsi->last_ino); |
1863 | if (IS_ERR(dentry)) { | 1964 | if (IS_ERR(dentry)) { |
1864 | ret = PTR_ERR(dentry); | 1965 | ret = PTR_ERR(dentry); |
1865 | goto err; | 1966 | goto err; |
@@ -1869,23 +1970,31 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1869 | if (ret) | 1970 | if (ret) |
1870 | goto err; | 1971 | goto err; |
1871 | 1972 | ||
1872 | class_dir = sel_make_dir(sb->s_root, "class", &sel_last_ino); | 1973 | fsi->class_dir = sel_make_dir(sb->s_root, "class", &fsi->last_ino); |
1873 | if (IS_ERR(class_dir)) { | 1974 | if (IS_ERR(fsi->class_dir)) { |
1874 | ret = PTR_ERR(class_dir); | 1975 | ret = PTR_ERR(fsi->class_dir); |
1875 | class_dir = NULL; | 1976 | fsi->class_dir = NULL; |
1876 | goto err; | 1977 | goto err; |
1877 | } | 1978 | } |
1878 | 1979 | ||
1879 | policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities", &sel_last_ino); | 1980 | fsi->policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities", |
1880 | if (IS_ERR(policycap_dir)) { | 1981 | &fsi->last_ino); |
1881 | ret = PTR_ERR(policycap_dir); | 1982 | if (IS_ERR(fsi->policycap_dir)) { |
1882 | policycap_dir = NULL; | 1983 | ret = PTR_ERR(fsi->policycap_dir); |
1984 | fsi->policycap_dir = NULL; | ||
1883 | goto err; | 1985 | goto err; |
1884 | } | 1986 | } |
1987 | |||
1988 | ret = sel_make_policy_nodes(fsi); | ||
1989 | if (ret) | ||
1990 | goto err; | ||
1885 | return 0; | 1991 | return 0; |
1886 | err: | 1992 | err: |
1887 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", | 1993 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", |
1888 | __func__); | 1994 | __func__); |
1995 | |||
1996 | selinux_fs_info_free(sb); | ||
1997 | |||
1889 | return ret; | 1998 | return ret; |
1890 | } | 1999 | } |
1891 | 2000 | ||
@@ -1895,16 +2004,25 @@ static struct dentry *sel_mount(struct file_system_type *fs_type, | |||
1895 | return mount_single(fs_type, flags, data, sel_fill_super); | 2004 | return mount_single(fs_type, flags, data, sel_fill_super); |
1896 | } | 2005 | } |
1897 | 2006 | ||
2007 | static void sel_kill_sb(struct super_block *sb) | ||
2008 | { | ||
2009 | selinux_fs_info_free(sb); | ||
2010 | kill_litter_super(sb); | ||
2011 | } | ||
2012 | |||
1898 | static struct file_system_type sel_fs_type = { | 2013 | static struct file_system_type sel_fs_type = { |
1899 | .name = "selinuxfs", | 2014 | .name = "selinuxfs", |
1900 | .mount = sel_mount, | 2015 | .mount = sel_mount, |
1901 | .kill_sb = kill_litter_super, | 2016 | .kill_sb = sel_kill_sb, |
1902 | }; | 2017 | }; |
1903 | 2018 | ||
1904 | struct vfsmount *selinuxfs_mount; | 2019 | struct vfsmount *selinuxfs_mount; |
2020 | struct path selinux_null; | ||
1905 | 2021 | ||
1906 | static int __init init_sel_fs(void) | 2022 | static int __init init_sel_fs(void) |
1907 | { | 2023 | { |
2024 | struct qstr null_name = QSTR_INIT(NULL_FILE_NAME, | ||
2025 | sizeof(NULL_FILE_NAME)-1); | ||
1908 | int err; | 2026 | int err; |
1909 | 2027 | ||
1910 | if (!selinux_enabled) | 2028 | if (!selinux_enabled) |
@@ -1926,6 +2044,13 @@ static int __init init_sel_fs(void) | |||
1926 | err = PTR_ERR(selinuxfs_mount); | 2044 | err = PTR_ERR(selinuxfs_mount); |
1927 | selinuxfs_mount = NULL; | 2045 | selinuxfs_mount = NULL; |
1928 | } | 2046 | } |
2047 | selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root, | ||
2048 | &null_name); | ||
2049 | if (IS_ERR(selinux_null.dentry)) { | ||
2050 | pr_err("selinuxfs: could not lookup null!\n"); | ||
2051 | err = PTR_ERR(selinux_null.dentry); | ||
2052 | selinux_null.dentry = NULL; | ||
2053 | } | ||
1929 | 2054 | ||
1930 | return err; | 2055 | return err; |
1931 | } | 2056 | } |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 2c3c7d010d8a..a2c9148b0662 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
@@ -655,7 +655,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) | |||
655 | 655 | ||
656 | return rc; | 656 | return rc; |
657 | } | 657 | } |
658 | void avtab_cache_init(void) | 658 | |
659 | void __init avtab_cache_init(void) | ||
659 | { | 660 | { |
660 | avtab_node_cachep = kmem_cache_create("avtab_node", | 661 | avtab_node_cachep = kmem_cache_create("avtab_node", |
661 | sizeof(struct avtab_node), | 662 | sizeof(struct avtab_node), |
@@ -664,9 +665,3 @@ void avtab_cache_init(void) | |||
664 | sizeof(struct avtab_extended_perms), | 665 | sizeof(struct avtab_extended_perms), |
665 | 0, SLAB_PANIC, NULL); | 666 | 0, SLAB_PANIC, NULL); |
666 | } | 667 | } |
667 | |||
668 | void avtab_cache_destroy(void) | ||
669 | { | ||
670 | kmem_cache_destroy(avtab_node_cachep); | ||
671 | kmem_cache_destroy(avtab_xperms_cachep); | ||
672 | } | ||
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 725853cadc42..0d652fad5319 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -114,9 +114,6 @@ struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); | |||
114 | 114 | ||
115 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); | 115 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); |
116 | 116 | ||
117 | void avtab_cache_init(void); | ||
118 | void avtab_cache_destroy(void); | ||
119 | |||
120 | #define MAX_AVTAB_HASH_BITS 16 | 117 | #define MAX_AVTAB_HASH_BITS 16 |
121 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 118 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
122 | 119 | ||
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index b6a78b09235c..5ae8c61b75bf 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -523,14 +523,9 @@ int ebitmap_write(struct ebitmap *e, void *fp) | |||
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | void ebitmap_cache_init(void) | 526 | void __init ebitmap_cache_init(void) |
527 | { | 527 | { |
528 | ebitmap_node_cachep = kmem_cache_create("ebitmap_node", | 528 | ebitmap_node_cachep = kmem_cache_create("ebitmap_node", |
529 | sizeof(struct ebitmap_node), | 529 | sizeof(struct ebitmap_node), |
530 | 0, SLAB_PANIC, NULL); | 530 | 0, SLAB_PANIC, NULL); |
531 | } | 531 | } |
532 | |||
533 | void ebitmap_cache_destroy(void) | ||
534 | { | ||
535 | kmem_cache_destroy(ebitmap_node_cachep); | ||
536 | } | ||
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index edf4fa39c60a..6aa7cf6a2197 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
@@ -131,9 +131,6 @@ void ebitmap_destroy(struct ebitmap *e); | |||
131 | int ebitmap_read(struct ebitmap *e, void *fp); | 131 | int ebitmap_read(struct ebitmap *e, void *fp); |
132 | int ebitmap_write(struct ebitmap *e, void *fp); | 132 | int ebitmap_write(struct ebitmap *e, void *fp); |
133 | 133 | ||
134 | void ebitmap_cache_init(void); | ||
135 | void ebitmap_cache_destroy(void); | ||
136 | |||
137 | #ifdef CONFIG_NETLABEL | 134 | #ifdef CONFIG_NETLABEL |
138 | int ebitmap_netlbl_export(struct ebitmap *ebmap, | 135 | int ebitmap_netlbl_export(struct ebitmap *ebmap, |
139 | struct netlbl_lsm_catmap **catmap); | 136 | struct netlbl_lsm_catmap **catmap); |
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index fe25b3fb2154..ebfdaa31ee32 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c | |||
@@ -169,14 +169,10 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) | |||
169 | info->slots_used = slots_used; | 169 | info->slots_used = slots_used; |
170 | info->max_chain_len = max_chain_len; | 170 | info->max_chain_len = max_chain_len; |
171 | } | 171 | } |
172 | void hashtab_cache_init(void) | 172 | |
173 | void __init hashtab_cache_init(void) | ||
173 | { | 174 | { |
174 | hashtab_node_cachep = kmem_cache_create("hashtab_node", | 175 | hashtab_node_cachep = kmem_cache_create("hashtab_node", |
175 | sizeof(struct hashtab_node), | 176 | sizeof(struct hashtab_node), |
176 | 0, SLAB_PANIC, NULL); | 177 | 0, SLAB_PANIC, NULL); |
177 | } | 178 | } |
178 | |||
179 | void hashtab_cache_destroy(void) | ||
180 | { | ||
181 | kmem_cache_destroy(hashtab_node_cachep); | ||
182 | } | ||
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 6183ee2a2e7a..3e3e42bfd150 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h | |||
@@ -85,8 +85,4 @@ int hashtab_map(struct hashtab *h, | |||
85 | /* Fill info with some hash table statistics */ | 85 | /* Fill info with some hash table statistics */ |
86 | void hashtab_stat(struct hashtab *h, struct hashtab_info *info); | 86 | void hashtab_stat(struct hashtab *h, struct hashtab_info *info); |
87 | 87 | ||
88 | /* Use kmem_cache for hashtab_node */ | ||
89 | void hashtab_cache_init(void); | ||
90 | void hashtab_cache_destroy(void); | ||
91 | |||
92 | #endif /* _SS_HASHTAB_H */ | 88 | #endif /* _SS_HASHTAB_H */ |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index ad982ce8bfa4..39475fb455bc 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -33,20 +33,20 @@ | |||
33 | * Return the length in bytes for the MLS fields of the | 33 | * Return the length in bytes for the MLS fields of the |
34 | * security context string representation of `context'. | 34 | * security context string representation of `context'. |
35 | */ | 35 | */ |
36 | int mls_compute_context_len(struct context *context) | 36 | int mls_compute_context_len(struct policydb *p, struct context *context) |
37 | { | 37 | { |
38 | int i, l, len, head, prev; | 38 | int i, l, len, head, prev; |
39 | char *nm; | 39 | char *nm; |
40 | struct ebitmap *e; | 40 | struct ebitmap *e; |
41 | struct ebitmap_node *node; | 41 | struct ebitmap_node *node; |
42 | 42 | ||
43 | if (!policydb.mls_enabled) | 43 | if (!p->mls_enabled) |
44 | return 0; | 44 | return 0; |
45 | 45 | ||
46 | len = 1; /* for the beginning ":" */ | 46 | len = 1; /* for the beginning ":" */ |
47 | for (l = 0; l < 2; l++) { | 47 | for (l = 0; l < 2; l++) { |
48 | int index_sens = context->range.level[l].sens; | 48 | int index_sens = context->range.level[l].sens; |
49 | len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1)); | 49 | len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1)); |
50 | 50 | ||
51 | /* categories */ | 51 | /* categories */ |
52 | head = -2; | 52 | head = -2; |
@@ -56,17 +56,17 @@ int mls_compute_context_len(struct context *context) | |||
56 | if (i - prev > 1) { | 56 | if (i - prev > 1) { |
57 | /* one or more negative bits are skipped */ | 57 | /* one or more negative bits are skipped */ |
58 | if (head != prev) { | 58 | if (head != prev) { |
59 | nm = sym_name(&policydb, SYM_CATS, prev); | 59 | nm = sym_name(p, SYM_CATS, prev); |
60 | len += strlen(nm) + 1; | 60 | len += strlen(nm) + 1; |
61 | } | 61 | } |
62 | nm = sym_name(&policydb, SYM_CATS, i); | 62 | nm = sym_name(p, SYM_CATS, i); |
63 | len += strlen(nm) + 1; | 63 | len += strlen(nm) + 1; |
64 | head = i; | 64 | head = i; |
65 | } | 65 | } |
66 | prev = i; | 66 | prev = i; |
67 | } | 67 | } |
68 | if (prev != head) { | 68 | if (prev != head) { |
69 | nm = sym_name(&policydb, SYM_CATS, prev); | 69 | nm = sym_name(p, SYM_CATS, prev); |
70 | len += strlen(nm) + 1; | 70 | len += strlen(nm) + 1; |
71 | } | 71 | } |
72 | if (l == 0) { | 72 | if (l == 0) { |
@@ -86,7 +86,8 @@ int mls_compute_context_len(struct context *context) | |||
86 | * the MLS fields of `context' into the string `*scontext'. | 86 | * the MLS fields of `context' into the string `*scontext'. |
87 | * Update `*scontext' to point to the end of the MLS fields. | 87 | * Update `*scontext' to point to the end of the MLS fields. |
88 | */ | 88 | */ |
89 | void mls_sid_to_context(struct context *context, | 89 | void mls_sid_to_context(struct policydb *p, |
90 | struct context *context, | ||
90 | char **scontext) | 91 | char **scontext) |
91 | { | 92 | { |
92 | char *scontextp, *nm; | 93 | char *scontextp, *nm; |
@@ -94,7 +95,7 @@ void mls_sid_to_context(struct context *context, | |||
94 | struct ebitmap *e; | 95 | struct ebitmap *e; |
95 | struct ebitmap_node *node; | 96 | struct ebitmap_node *node; |
96 | 97 | ||
97 | if (!policydb.mls_enabled) | 98 | if (!p->mls_enabled) |
98 | return; | 99 | return; |
99 | 100 | ||
100 | scontextp = *scontext; | 101 | scontextp = *scontext; |
@@ -103,7 +104,7 @@ void mls_sid_to_context(struct context *context, | |||
103 | scontextp++; | 104 | scontextp++; |
104 | 105 | ||
105 | for (l = 0; l < 2; l++) { | 106 | for (l = 0; l < 2; l++) { |
106 | strcpy(scontextp, sym_name(&policydb, SYM_LEVELS, | 107 | strcpy(scontextp, sym_name(p, SYM_LEVELS, |
107 | context->range.level[l].sens - 1)); | 108 | context->range.level[l].sens - 1)); |
108 | scontextp += strlen(scontextp); | 109 | scontextp += strlen(scontextp); |
109 | 110 | ||
@@ -119,7 +120,7 @@ void mls_sid_to_context(struct context *context, | |||
119 | *scontextp++ = '.'; | 120 | *scontextp++ = '.'; |
120 | else | 121 | else |
121 | *scontextp++ = ','; | 122 | *scontextp++ = ','; |
122 | nm = sym_name(&policydb, SYM_CATS, prev); | 123 | nm = sym_name(p, SYM_CATS, prev); |
123 | strcpy(scontextp, nm); | 124 | strcpy(scontextp, nm); |
124 | scontextp += strlen(nm); | 125 | scontextp += strlen(nm); |
125 | } | 126 | } |
@@ -127,7 +128,7 @@ void mls_sid_to_context(struct context *context, | |||
127 | *scontextp++ = ':'; | 128 | *scontextp++ = ':'; |
128 | else | 129 | else |
129 | *scontextp++ = ','; | 130 | *scontextp++ = ','; |
130 | nm = sym_name(&policydb, SYM_CATS, i); | 131 | nm = sym_name(p, SYM_CATS, i); |
131 | strcpy(scontextp, nm); | 132 | strcpy(scontextp, nm); |
132 | scontextp += strlen(nm); | 133 | scontextp += strlen(nm); |
133 | head = i; | 134 | head = i; |
@@ -140,7 +141,7 @@ void mls_sid_to_context(struct context *context, | |||
140 | *scontextp++ = '.'; | 141 | *scontextp++ = '.'; |
141 | else | 142 | else |
142 | *scontextp++ = ','; | 143 | *scontextp++ = ','; |
143 | nm = sym_name(&policydb, SYM_CATS, prev); | 144 | nm = sym_name(p, SYM_CATS, prev); |
144 | strcpy(scontextp, nm); | 145 | strcpy(scontextp, nm); |
145 | scontextp += strlen(nm); | 146 | scontextp += strlen(nm); |
146 | } | 147 | } |
@@ -375,12 +376,13 @@ out: | |||
375 | * the string `str'. This function will allocate temporary memory with the | 376 | * the string `str'. This function will allocate temporary memory with the |
376 | * given constraints of gfp_mask. | 377 | * given constraints of gfp_mask. |
377 | */ | 378 | */ |
378 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | 379 | int mls_from_string(struct policydb *p, char *str, struct context *context, |
380 | gfp_t gfp_mask) | ||
379 | { | 381 | { |
380 | char *tmpstr, *freestr; | 382 | char *tmpstr, *freestr; |
381 | int rc; | 383 | int rc; |
382 | 384 | ||
383 | if (!policydb.mls_enabled) | 385 | if (!p->mls_enabled) |
384 | return -EINVAL; | 386 | return -EINVAL; |
385 | 387 | ||
386 | /* we need freestr because mls_context_to_sid will change | 388 | /* we need freestr because mls_context_to_sid will change |
@@ -389,7 +391,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
389 | if (!tmpstr) { | 391 | if (!tmpstr) { |
390 | rc = -ENOMEM; | 392 | rc = -ENOMEM; |
391 | } else { | 393 | } else { |
392 | rc = mls_context_to_sid(&policydb, ':', &tmpstr, context, | 394 | rc = mls_context_to_sid(p, ':', &tmpstr, context, |
393 | NULL, SECSID_NULL); | 395 | NULL, SECSID_NULL); |
394 | kfree(freestr); | 396 | kfree(freestr); |
395 | } | 397 | } |
@@ -417,10 +419,11 @@ int mls_range_set(struct context *context, | |||
417 | return rc; | 419 | return rc; |
418 | } | 420 | } |
419 | 421 | ||
420 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 422 | int mls_setup_user_range(struct policydb *p, |
423 | struct context *fromcon, struct user_datum *user, | ||
421 | struct context *usercon) | 424 | struct context *usercon) |
422 | { | 425 | { |
423 | if (policydb.mls_enabled) { | 426 | if (p->mls_enabled) { |
424 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); | 427 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
425 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | 428 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); |
426 | struct mls_level *user_low = &(user->range.level[0]); | 429 | struct mls_level *user_low = &(user->range.level[0]); |
@@ -470,7 +473,7 @@ int mls_convert_context(struct policydb *oldp, | |||
470 | struct ebitmap_node *node; | 473 | struct ebitmap_node *node; |
471 | int l, i; | 474 | int l, i; |
472 | 475 | ||
473 | if (!policydb.mls_enabled) | 476 | if (!oldp->mls_enabled || !newp->mls_enabled) |
474 | return 0; | 477 | return 0; |
475 | 478 | ||
476 | for (l = 0; l < 2; l++) { | 479 | for (l = 0; l < 2; l++) { |
@@ -503,7 +506,8 @@ int mls_convert_context(struct policydb *oldp, | |||
503 | return 0; | 506 | return 0; |
504 | } | 507 | } |
505 | 508 | ||
506 | int mls_compute_sid(struct context *scontext, | 509 | int mls_compute_sid(struct policydb *p, |
510 | struct context *scontext, | ||
507 | struct context *tcontext, | 511 | struct context *tcontext, |
508 | u16 tclass, | 512 | u16 tclass, |
509 | u32 specified, | 513 | u32 specified, |
@@ -515,7 +519,7 @@ int mls_compute_sid(struct context *scontext, | |||
515 | struct class_datum *cladatum; | 519 | struct class_datum *cladatum; |
516 | int default_range = 0; | 520 | int default_range = 0; |
517 | 521 | ||
518 | if (!policydb.mls_enabled) | 522 | if (!p->mls_enabled) |
519 | return 0; | 523 | return 0; |
520 | 524 | ||
521 | switch (specified) { | 525 | switch (specified) { |
@@ -524,12 +528,12 @@ int mls_compute_sid(struct context *scontext, | |||
524 | rtr.source_type = scontext->type; | 528 | rtr.source_type = scontext->type; |
525 | rtr.target_type = tcontext->type; | 529 | rtr.target_type = tcontext->type; |
526 | rtr.target_class = tclass; | 530 | rtr.target_class = tclass; |
527 | r = hashtab_search(policydb.range_tr, &rtr); | 531 | r = hashtab_search(p->range_tr, &rtr); |
528 | if (r) | 532 | if (r) |
529 | return mls_range_set(newcontext, r); | 533 | return mls_range_set(newcontext, r); |
530 | 534 | ||
531 | if (tclass && tclass <= policydb.p_classes.nprim) { | 535 | if (tclass && tclass <= p->p_classes.nprim) { |
532 | cladatum = policydb.class_val_to_struct[tclass - 1]; | 536 | cladatum = p->class_val_to_struct[tclass - 1]; |
533 | if (cladatum) | 537 | if (cladatum) |
534 | default_range = cladatum->default_range; | 538 | default_range = cladatum->default_range; |
535 | } | 539 | } |
@@ -551,7 +555,7 @@ int mls_compute_sid(struct context *scontext, | |||
551 | 555 | ||
552 | /* Fallthrough */ | 556 | /* Fallthrough */ |
553 | case AVTAB_CHANGE: | 557 | case AVTAB_CHANGE: |
554 | if ((tclass == policydb.process_class) || (sock == true)) | 558 | if ((tclass == p->process_class) || (sock == true)) |
555 | /* Use the process MLS attributes. */ | 559 | /* Use the process MLS attributes. */ |
556 | return mls_context_cpy(newcontext, scontext); | 560 | return mls_context_cpy(newcontext, scontext); |
557 | else | 561 | else |
@@ -577,10 +581,11 @@ int mls_compute_sid(struct context *scontext, | |||
577 | * NetLabel MLS sensitivity level field. | 581 | * NetLabel MLS sensitivity level field. |
578 | * | 582 | * |
579 | */ | 583 | */ |
580 | void mls_export_netlbl_lvl(struct context *context, | 584 | void mls_export_netlbl_lvl(struct policydb *p, |
585 | struct context *context, | ||
581 | struct netlbl_lsm_secattr *secattr) | 586 | struct netlbl_lsm_secattr *secattr) |
582 | { | 587 | { |
583 | if (!policydb.mls_enabled) | 588 | if (!p->mls_enabled) |
584 | return; | 589 | return; |
585 | 590 | ||
586 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 591 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
@@ -597,10 +602,11 @@ void mls_export_netlbl_lvl(struct context *context, | |||
597 | * NetLabel MLS sensitivity level into the context. | 602 | * NetLabel MLS sensitivity level into the context. |
598 | * | 603 | * |
599 | */ | 604 | */ |
600 | void mls_import_netlbl_lvl(struct context *context, | 605 | void mls_import_netlbl_lvl(struct policydb *p, |
606 | struct context *context, | ||
601 | struct netlbl_lsm_secattr *secattr) | 607 | struct netlbl_lsm_secattr *secattr) |
602 | { | 608 | { |
603 | if (!policydb.mls_enabled) | 609 | if (!p->mls_enabled) |
604 | return; | 610 | return; |
605 | 611 | ||
606 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 612 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
@@ -617,12 +623,13 @@ void mls_import_netlbl_lvl(struct context *context, | |||
617 | * MLS category field. Returns zero on success, negative values on failure. | 623 | * MLS category field. Returns zero on success, negative values on failure. |
618 | * | 624 | * |
619 | */ | 625 | */ |
620 | int mls_export_netlbl_cat(struct context *context, | 626 | int mls_export_netlbl_cat(struct policydb *p, |
627 | struct context *context, | ||
621 | struct netlbl_lsm_secattr *secattr) | 628 | struct netlbl_lsm_secattr *secattr) |
622 | { | 629 | { |
623 | int rc; | 630 | int rc; |
624 | 631 | ||
625 | if (!policydb.mls_enabled) | 632 | if (!p->mls_enabled) |
626 | return 0; | 633 | return 0; |
627 | 634 | ||
628 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 635 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
@@ -645,12 +652,13 @@ int mls_export_netlbl_cat(struct context *context, | |||
645 | * negative values on failure. | 652 | * negative values on failure. |
646 | * | 653 | * |
647 | */ | 654 | */ |
648 | int mls_import_netlbl_cat(struct context *context, | 655 | int mls_import_netlbl_cat(struct policydb *p, |
656 | struct context *context, | ||
649 | struct netlbl_lsm_secattr *secattr) | 657 | struct netlbl_lsm_secattr *secattr) |
650 | { | 658 | { |
651 | int rc; | 659 | int rc; |
652 | 660 | ||
653 | if (!policydb.mls_enabled) | 661 | if (!p->mls_enabled) |
654 | return 0; | 662 | return 0; |
655 | 663 | ||
656 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 664 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 131d76266ea5..9a3ff7af70ad 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -25,8 +25,9 @@ | |||
25 | #include "context.h" | 25 | #include "context.h" |
26 | #include "policydb.h" | 26 | #include "policydb.h" |
27 | 27 | ||
28 | int mls_compute_context_len(struct context *context); | 28 | int mls_compute_context_len(struct policydb *p, struct context *context); |
29 | void mls_sid_to_context(struct context *context, char **scontext); | 29 | void mls_sid_to_context(struct policydb *p, struct context *context, |
30 | char **scontext); | ||
30 | int mls_context_isvalid(struct policydb *p, struct context *c); | 31 | int mls_context_isvalid(struct policydb *p, struct context *c); |
31 | int mls_range_isvalid(struct policydb *p, struct mls_range *r); | 32 | int mls_range_isvalid(struct policydb *p, struct mls_range *r); |
32 | int mls_level_isvalid(struct policydb *p, struct mls_level *l); | 33 | int mls_level_isvalid(struct policydb *p, struct mls_level *l); |
@@ -38,7 +39,8 @@ int mls_context_to_sid(struct policydb *p, | |||
38 | struct sidtab *s, | 39 | struct sidtab *s, |
39 | u32 def_sid); | 40 | u32 def_sid); |
40 | 41 | ||
41 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | 42 | int mls_from_string(struct policydb *p, char *str, struct context *context, |
43 | gfp_t gfp_mask); | ||
42 | 44 | ||
43 | int mls_range_set(struct context *context, struct mls_range *range); | 45 | int mls_range_set(struct context *context, struct mls_range *range); |
44 | 46 | ||
@@ -46,42 +48,52 @@ int mls_convert_context(struct policydb *oldp, | |||
46 | struct policydb *newp, | 48 | struct policydb *newp, |
47 | struct context *context); | 49 | struct context *context); |
48 | 50 | ||
49 | int mls_compute_sid(struct context *scontext, | 51 | int mls_compute_sid(struct policydb *p, |
52 | struct context *scontext, | ||
50 | struct context *tcontext, | 53 | struct context *tcontext, |
51 | u16 tclass, | 54 | u16 tclass, |
52 | u32 specified, | 55 | u32 specified, |
53 | struct context *newcontext, | 56 | struct context *newcontext, |
54 | bool sock); | 57 | bool sock); |
55 | 58 | ||
56 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 59 | int mls_setup_user_range(struct policydb *p, |
60 | struct context *fromcon, struct user_datum *user, | ||
57 | struct context *usercon); | 61 | struct context *usercon); |
58 | 62 | ||
59 | #ifdef CONFIG_NETLABEL | 63 | #ifdef CONFIG_NETLABEL |
60 | void mls_export_netlbl_lvl(struct context *context, | 64 | void mls_export_netlbl_lvl(struct policydb *p, |
65 | struct context *context, | ||
61 | struct netlbl_lsm_secattr *secattr); | 66 | struct netlbl_lsm_secattr *secattr); |
62 | void mls_import_netlbl_lvl(struct context *context, | 67 | void mls_import_netlbl_lvl(struct policydb *p, |
68 | struct context *context, | ||
63 | struct netlbl_lsm_secattr *secattr); | 69 | struct netlbl_lsm_secattr *secattr); |
64 | int mls_export_netlbl_cat(struct context *context, | 70 | int mls_export_netlbl_cat(struct policydb *p, |
71 | struct context *context, | ||
65 | struct netlbl_lsm_secattr *secattr); | 72 | struct netlbl_lsm_secattr *secattr); |
66 | int mls_import_netlbl_cat(struct context *context, | 73 | int mls_import_netlbl_cat(struct policydb *p, |
74 | struct context *context, | ||
67 | struct netlbl_lsm_secattr *secattr); | 75 | struct netlbl_lsm_secattr *secattr); |
68 | #else | 76 | #else |
69 | static inline void mls_export_netlbl_lvl(struct context *context, | 77 | static inline void mls_export_netlbl_lvl(struct policydb *p, |
78 | struct context *context, | ||
70 | struct netlbl_lsm_secattr *secattr) | 79 | struct netlbl_lsm_secattr *secattr) |
71 | { | 80 | { |
72 | return; | 81 | return; |
73 | } | 82 | } |
74 | static inline void mls_import_netlbl_lvl(struct context *context, | 83 | static inline void mls_import_netlbl_lvl(struct policydb *p, |
84 | struct context *context, | ||
75 | struct netlbl_lsm_secattr *secattr) | 85 | struct netlbl_lsm_secattr *secattr) |
76 | { | 86 | { |
77 | return; | 87 | return; |
78 | } | 88 | } |
79 | static inline int mls_export_netlbl_cat(struct context *context, | 89 | static inline int mls_export_netlbl_cat(struct policydb *p, |
90 | struct context *context, | ||
80 | struct netlbl_lsm_secattr *secattr) | 91 | struct netlbl_lsm_secattr *secattr) |
81 | { | 92 | { |
82 | return -ENOMEM; | 93 | return -ENOMEM; |
83 | } | 94 | } |
84 | static inline int mls_import_netlbl_cat(struct context *context, | 95 | static inline int mls_import_netlbl_cat(struct policydb *p, |
96 | struct context *context, | ||
85 | struct netlbl_lsm_secattr *secattr) | 97 | struct netlbl_lsm_secattr *secattr) |
86 | { | 98 | { |
87 | return -ENOMEM; | 99 | return -ENOMEM; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8900ea5cbabf..8057e19dc15f 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -80,53 +80,32 @@ char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = { | |||
80 | "nnp_nosuid_transition" | 80 | "nnp_nosuid_transition" |
81 | }; | 81 | }; |
82 | 82 | ||
83 | int selinux_policycap_netpeer; | 83 | static struct selinux_ss selinux_ss; |
84 | int selinux_policycap_openperm; | ||
85 | int selinux_policycap_extsockclass; | ||
86 | int selinux_policycap_alwaysnetwork; | ||
87 | int selinux_policycap_cgroupseclabel; | ||
88 | int selinux_policycap_nnp_nosuid_transition; | ||
89 | 84 | ||
90 | static DEFINE_RWLOCK(policy_rwlock); | 85 | void selinux_ss_init(struct selinux_ss **ss) |
91 | 86 | { | |
92 | static struct sidtab sidtab; | 87 | rwlock_init(&selinux_ss.policy_rwlock); |
93 | struct policydb policydb; | 88 | mutex_init(&selinux_ss.status_lock); |
94 | int ss_initialized; | 89 | *ss = &selinux_ss; |
95 | 90 | } | |
96 | /* | ||
97 | * The largest sequence number that has been used when | ||
98 | * providing an access decision to the access vector cache. | ||
99 | * The sequence number only changes when a policy change | ||
100 | * occurs. | ||
101 | */ | ||
102 | static u32 latest_granting; | ||
103 | 91 | ||
104 | /* Forward declaration. */ | 92 | /* Forward declaration. */ |
105 | static int context_struct_to_string(struct context *context, char **scontext, | 93 | static int context_struct_to_string(struct policydb *policydb, |
94 | struct context *context, | ||
95 | char **scontext, | ||
106 | u32 *scontext_len); | 96 | u32 *scontext_len); |
107 | 97 | ||
108 | static void context_struct_compute_av(struct context *scontext, | 98 | static void context_struct_compute_av(struct policydb *policydb, |
109 | struct context *tcontext, | 99 | struct context *scontext, |
110 | u16 tclass, | 100 | struct context *tcontext, |
111 | struct av_decision *avd, | 101 | u16 tclass, |
112 | struct extended_perms *xperms); | 102 | struct av_decision *avd, |
113 | 103 | struct extended_perms *xperms); | |
114 | struct selinux_mapping { | ||
115 | u16 value; /* policy value */ | ||
116 | unsigned num_perms; | ||
117 | u32 perms[sizeof(u32) * 8]; | ||
118 | }; | ||
119 | |||
120 | static struct selinux_mapping *current_mapping; | ||
121 | static u16 current_mapping_size; | ||
122 | 104 | ||
123 | static int selinux_set_mapping(struct policydb *pol, | 105 | static int selinux_set_mapping(struct policydb *pol, |
124 | struct security_class_mapping *map, | 106 | struct security_class_mapping *map, |
125 | struct selinux_mapping **out_map_p, | 107 | struct selinux_map *out_map) |
126 | u16 *out_map_size) | ||
127 | { | 108 | { |
128 | struct selinux_mapping *out_map = NULL; | ||
129 | size_t size = sizeof(struct selinux_mapping); | ||
130 | u16 i, j; | 109 | u16 i, j; |
131 | unsigned k; | 110 | unsigned k; |
132 | bool print_unknown_handle = false; | 111 | bool print_unknown_handle = false; |
@@ -139,15 +118,15 @@ static int selinux_set_mapping(struct policydb *pol, | |||
139 | i++; | 118 | i++; |
140 | 119 | ||
141 | /* Allocate space for the class records, plus one for class zero */ | 120 | /* Allocate space for the class records, plus one for class zero */ |
142 | out_map = kcalloc(++i, size, GFP_ATOMIC); | 121 | out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC); |
143 | if (!out_map) | 122 | if (!out_map->mapping) |
144 | return -ENOMEM; | 123 | return -ENOMEM; |
145 | 124 | ||
146 | /* Store the raw class and permission values */ | 125 | /* Store the raw class and permission values */ |
147 | j = 0; | 126 | j = 0; |
148 | while (map[j].name) { | 127 | while (map[j].name) { |
149 | struct security_class_mapping *p_in = map + (j++); | 128 | struct security_class_mapping *p_in = map + (j++); |
150 | struct selinux_mapping *p_out = out_map + j; | 129 | struct selinux_mapping *p_out = out_map->mapping + j; |
151 | 130 | ||
152 | /* An empty class string skips ahead */ | 131 | /* An empty class string skips ahead */ |
153 | if (!strcmp(p_in->name, "")) { | 132 | if (!strcmp(p_in->name, "")) { |
@@ -194,11 +173,11 @@ static int selinux_set_mapping(struct policydb *pol, | |||
194 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | 173 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", |
195 | pol->allow_unknown ? "allowed" : "denied"); | 174 | pol->allow_unknown ? "allowed" : "denied"); |
196 | 175 | ||
197 | *out_map_p = out_map; | 176 | out_map->size = i; |
198 | *out_map_size = i; | ||
199 | return 0; | 177 | return 0; |
200 | err: | 178 | err: |
201 | kfree(out_map); | 179 | kfree(out_map->mapping); |
180 | out_map->mapping = NULL; | ||
202 | return -EINVAL; | 181 | return -EINVAL; |
203 | } | 182 | } |
204 | 183 | ||
@@ -206,10 +185,10 @@ err: | |||
206 | * Get real, policy values from mapped values | 185 | * Get real, policy values from mapped values |
207 | */ | 186 | */ |
208 | 187 | ||
209 | static u16 unmap_class(u16 tclass) | 188 | static u16 unmap_class(struct selinux_map *map, u16 tclass) |
210 | { | 189 | { |
211 | if (tclass < current_mapping_size) | 190 | if (tclass < map->size) |
212 | return current_mapping[tclass].value; | 191 | return map->mapping[tclass].value; |
213 | 192 | ||
214 | return tclass; | 193 | return tclass; |
215 | } | 194 | } |
@@ -217,42 +196,44 @@ static u16 unmap_class(u16 tclass) | |||
217 | /* | 196 | /* |
218 | * Get kernel value for class from its policy value | 197 | * Get kernel value for class from its policy value |
219 | */ | 198 | */ |
220 | static u16 map_class(u16 pol_value) | 199 | static u16 map_class(struct selinux_map *map, u16 pol_value) |
221 | { | 200 | { |
222 | u16 i; | 201 | u16 i; |
223 | 202 | ||
224 | for (i = 1; i < current_mapping_size; i++) { | 203 | for (i = 1; i < map->size; i++) { |
225 | if (current_mapping[i].value == pol_value) | 204 | if (map->mapping[i].value == pol_value) |
226 | return i; | 205 | return i; |
227 | } | 206 | } |
228 | 207 | ||
229 | return SECCLASS_NULL; | 208 | return SECCLASS_NULL; |
230 | } | 209 | } |
231 | 210 | ||
232 | static void map_decision(u16 tclass, struct av_decision *avd, | 211 | static void map_decision(struct selinux_map *map, |
212 | u16 tclass, struct av_decision *avd, | ||
233 | int allow_unknown) | 213 | int allow_unknown) |
234 | { | 214 | { |
235 | if (tclass < current_mapping_size) { | 215 | if (tclass < map->size) { |
236 | unsigned i, n = current_mapping[tclass].num_perms; | 216 | struct selinux_mapping *mapping = &map->mapping[tclass]; |
217 | unsigned int i, n = mapping->num_perms; | ||
237 | u32 result; | 218 | u32 result; |
238 | 219 | ||
239 | for (i = 0, result = 0; i < n; i++) { | 220 | for (i = 0, result = 0; i < n; i++) { |
240 | if (avd->allowed & current_mapping[tclass].perms[i]) | 221 | if (avd->allowed & mapping->perms[i]) |
241 | result |= 1<<i; | 222 | result |= 1<<i; |
242 | if (allow_unknown && !current_mapping[tclass].perms[i]) | 223 | if (allow_unknown && !mapping->perms[i]) |
243 | result |= 1<<i; | 224 | result |= 1<<i; |
244 | } | 225 | } |
245 | avd->allowed = result; | 226 | avd->allowed = result; |
246 | 227 | ||
247 | for (i = 0, result = 0; i < n; i++) | 228 | for (i = 0, result = 0; i < n; i++) |
248 | if (avd->auditallow & current_mapping[tclass].perms[i]) | 229 | if (avd->auditallow & mapping->perms[i]) |
249 | result |= 1<<i; | 230 | result |= 1<<i; |
250 | avd->auditallow = result; | 231 | avd->auditallow = result; |
251 | 232 | ||
252 | for (i = 0, result = 0; i < n; i++) { | 233 | for (i = 0, result = 0; i < n; i++) { |
253 | if (avd->auditdeny & current_mapping[tclass].perms[i]) | 234 | if (avd->auditdeny & mapping->perms[i]) |
254 | result |= 1<<i; | 235 | result |= 1<<i; |
255 | if (!allow_unknown && !current_mapping[tclass].perms[i]) | 236 | if (!allow_unknown && !mapping->perms[i]) |
256 | result |= 1<<i; | 237 | result |= 1<<i; |
257 | } | 238 | } |
258 | /* | 239 | /* |
@@ -266,9 +247,11 @@ static void map_decision(u16 tclass, struct av_decision *avd, | |||
266 | } | 247 | } |
267 | } | 248 | } |
268 | 249 | ||
269 | int security_mls_enabled(void) | 250 | int security_mls_enabled(struct selinux_state *state) |
270 | { | 251 | { |
271 | return policydb.mls_enabled; | 252 | struct policydb *p = &state->ss->policydb; |
253 | |||
254 | return p->mls_enabled; | ||
272 | } | 255 | } |
273 | 256 | ||
274 | /* | 257 | /* |
@@ -282,7 +265,8 @@ int security_mls_enabled(void) | |||
282 | * of the process performing the transition. All other callers of | 265 | * of the process performing the transition. All other callers of |
283 | * constraint_expr_eval should pass in NULL for xcontext. | 266 | * constraint_expr_eval should pass in NULL for xcontext. |
284 | */ | 267 | */ |
285 | static int constraint_expr_eval(struct context *scontext, | 268 | static int constraint_expr_eval(struct policydb *policydb, |
269 | struct context *scontext, | ||
286 | struct context *tcontext, | 270 | struct context *tcontext, |
287 | struct context *xcontext, | 271 | struct context *xcontext, |
288 | struct constraint_expr *cexpr) | 272 | struct constraint_expr *cexpr) |
@@ -326,8 +310,8 @@ static int constraint_expr_eval(struct context *scontext, | |||
326 | case CEXPR_ROLE: | 310 | case CEXPR_ROLE: |
327 | val1 = scontext->role; | 311 | val1 = scontext->role; |
328 | val2 = tcontext->role; | 312 | val2 = tcontext->role; |
329 | r1 = policydb.role_val_to_struct[val1 - 1]; | 313 | r1 = policydb->role_val_to_struct[val1 - 1]; |
330 | r2 = policydb.role_val_to_struct[val2 - 1]; | 314 | r2 = policydb->role_val_to_struct[val2 - 1]; |
331 | switch (e->op) { | 315 | switch (e->op) { |
332 | case CEXPR_DOM: | 316 | case CEXPR_DOM: |
333 | s[++sp] = ebitmap_get_bit(&r1->dominates, | 317 | s[++sp] = ebitmap_get_bit(&r1->dominates, |
@@ -472,7 +456,8 @@ static int dump_masked_av_helper(void *k, void *d, void *args) | |||
472 | return 0; | 456 | return 0; |
473 | } | 457 | } |
474 | 458 | ||
475 | static void security_dump_masked_av(struct context *scontext, | 459 | static void security_dump_masked_av(struct policydb *policydb, |
460 | struct context *scontext, | ||
476 | struct context *tcontext, | 461 | struct context *tcontext, |
477 | u16 tclass, | 462 | u16 tclass, |
478 | u32 permissions, | 463 | u32 permissions, |
@@ -492,8 +477,8 @@ static void security_dump_masked_av(struct context *scontext, | |||
492 | if (!permissions) | 477 | if (!permissions) |
493 | return; | 478 | return; |
494 | 479 | ||
495 | tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1); | 480 | tclass_name = sym_name(policydb, SYM_CLASSES, tclass - 1); |
496 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | 481 | tclass_dat = policydb->class_val_to_struct[tclass - 1]; |
497 | common_dat = tclass_dat->comdatum; | 482 | common_dat = tclass_dat->comdatum; |
498 | 483 | ||
499 | /* init permission_names */ | 484 | /* init permission_names */ |
@@ -507,11 +492,11 @@ static void security_dump_masked_av(struct context *scontext, | |||
507 | goto out; | 492 | goto out; |
508 | 493 | ||
509 | /* get scontext/tcontext in text form */ | 494 | /* get scontext/tcontext in text form */ |
510 | if (context_struct_to_string(scontext, | 495 | if (context_struct_to_string(policydb, scontext, |
511 | &scontext_name, &length) < 0) | 496 | &scontext_name, &length) < 0) |
512 | goto out; | 497 | goto out; |
513 | 498 | ||
514 | if (context_struct_to_string(tcontext, | 499 | if (context_struct_to_string(policydb, tcontext, |
515 | &tcontext_name, &length) < 0) | 500 | &tcontext_name, &length) < 0) |
516 | goto out; | 501 | goto out; |
517 | 502 | ||
@@ -550,7 +535,8 @@ out: | |||
550 | * security_boundary_permission - drops violated permissions | 535 | * security_boundary_permission - drops violated permissions |
551 | * on boundary constraint. | 536 | * on boundary constraint. |
552 | */ | 537 | */ |
553 | static void type_attribute_bounds_av(struct context *scontext, | 538 | static void type_attribute_bounds_av(struct policydb *policydb, |
539 | struct context *scontext, | ||
554 | struct context *tcontext, | 540 | struct context *tcontext, |
555 | u16 tclass, | 541 | u16 tclass, |
556 | struct av_decision *avd) | 542 | struct av_decision *avd) |
@@ -562,14 +548,14 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
562 | struct type_datum *target; | 548 | struct type_datum *target; |
563 | u32 masked = 0; | 549 | u32 masked = 0; |
564 | 550 | ||
565 | source = flex_array_get_ptr(policydb.type_val_to_struct_array, | 551 | source = flex_array_get_ptr(policydb->type_val_to_struct_array, |
566 | scontext->type - 1); | 552 | scontext->type - 1); |
567 | BUG_ON(!source); | 553 | BUG_ON(!source); |
568 | 554 | ||
569 | if (!source->bounds) | 555 | if (!source->bounds) |
570 | return; | 556 | return; |
571 | 557 | ||
572 | target = flex_array_get_ptr(policydb.type_val_to_struct_array, | 558 | target = flex_array_get_ptr(policydb->type_val_to_struct_array, |
573 | tcontext->type - 1); | 559 | tcontext->type - 1); |
574 | BUG_ON(!target); | 560 | BUG_ON(!target); |
575 | 561 | ||
@@ -584,7 +570,7 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
584 | tcontextp = &lo_tcontext; | 570 | tcontextp = &lo_tcontext; |
585 | } | 571 | } |
586 | 572 | ||
587 | context_struct_compute_av(&lo_scontext, | 573 | context_struct_compute_av(policydb, &lo_scontext, |
588 | tcontextp, | 574 | tcontextp, |
589 | tclass, | 575 | tclass, |
590 | &lo_avd, | 576 | &lo_avd, |
@@ -599,7 +585,7 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
599 | avd->allowed &= ~masked; | 585 | avd->allowed &= ~masked; |
600 | 586 | ||
601 | /* audit masked permissions */ | 587 | /* audit masked permissions */ |
602 | security_dump_masked_av(scontext, tcontext, | 588 | security_dump_masked_av(policydb, scontext, tcontext, |
603 | tclass, masked, "bounds"); | 589 | tclass, masked, "bounds"); |
604 | } | 590 | } |
605 | 591 | ||
@@ -632,11 +618,12 @@ void services_compute_xperms_drivers( | |||
632 | * Compute access vectors and extended permissions based on a context | 618 | * Compute access vectors and extended permissions based on a context |
633 | * structure pair for the permissions in a particular class. | 619 | * structure pair for the permissions in a particular class. |
634 | */ | 620 | */ |
635 | static void context_struct_compute_av(struct context *scontext, | 621 | static void context_struct_compute_av(struct policydb *policydb, |
636 | struct context *tcontext, | 622 | struct context *scontext, |
637 | u16 tclass, | 623 | struct context *tcontext, |
638 | struct av_decision *avd, | 624 | u16 tclass, |
639 | struct extended_perms *xperms) | 625 | struct av_decision *avd, |
626 | struct extended_perms *xperms) | ||
640 | { | 627 | { |
641 | struct constraint_node *constraint; | 628 | struct constraint_node *constraint; |
642 | struct role_allow *ra; | 629 | struct role_allow *ra; |
@@ -655,13 +642,13 @@ static void context_struct_compute_av(struct context *scontext, | |||
655 | xperms->len = 0; | 642 | xperms->len = 0; |
656 | } | 643 | } |
657 | 644 | ||
658 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { | 645 | if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { |
659 | if (printk_ratelimit()) | 646 | if (printk_ratelimit()) |
660 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); | 647 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
661 | return; | 648 | return; |
662 | } | 649 | } |
663 | 650 | ||
664 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 651 | tclass_datum = policydb->class_val_to_struct[tclass - 1]; |
665 | 652 | ||
666 | /* | 653 | /* |
667 | * If a specific type enforcement rule was defined for | 654 | * If a specific type enforcement rule was defined for |
@@ -669,15 +656,18 @@ static void context_struct_compute_av(struct context *scontext, | |||
669 | */ | 656 | */ |
670 | avkey.target_class = tclass; | 657 | avkey.target_class = tclass; |
671 | avkey.specified = AVTAB_AV | AVTAB_XPERMS; | 658 | avkey.specified = AVTAB_AV | AVTAB_XPERMS; |
672 | sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); | 659 | sattr = flex_array_get(policydb->type_attr_map_array, |
660 | scontext->type - 1); | ||
673 | BUG_ON(!sattr); | 661 | BUG_ON(!sattr); |
674 | tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); | 662 | tattr = flex_array_get(policydb->type_attr_map_array, |
663 | tcontext->type - 1); | ||
675 | BUG_ON(!tattr); | 664 | BUG_ON(!tattr); |
676 | ebitmap_for_each_positive_bit(sattr, snode, i) { | 665 | ebitmap_for_each_positive_bit(sattr, snode, i) { |
677 | ebitmap_for_each_positive_bit(tattr, tnode, j) { | 666 | ebitmap_for_each_positive_bit(tattr, tnode, j) { |
678 | avkey.source_type = i + 1; | 667 | avkey.source_type = i + 1; |
679 | avkey.target_type = j + 1; | 668 | avkey.target_type = j + 1; |
680 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | 669 | for (node = avtab_search_node(&policydb->te_avtab, |
670 | &avkey); | ||
681 | node; | 671 | node; |
682 | node = avtab_search_node_next(node, avkey.specified)) { | 672 | node = avtab_search_node_next(node, avkey.specified)) { |
683 | if (node->key.specified == AVTAB_ALLOWED) | 673 | if (node->key.specified == AVTAB_ALLOWED) |
@@ -691,7 +681,7 @@ static void context_struct_compute_av(struct context *scontext, | |||
691 | } | 681 | } |
692 | 682 | ||
693 | /* Check conditional av table for additional permissions */ | 683 | /* Check conditional av table for additional permissions */ |
694 | cond_compute_av(&policydb.te_cond_avtab, &avkey, | 684 | cond_compute_av(&policydb->te_cond_avtab, &avkey, |
695 | avd, xperms); | 685 | avd, xperms); |
696 | 686 | ||
697 | } | 687 | } |
@@ -704,7 +694,7 @@ static void context_struct_compute_av(struct context *scontext, | |||
704 | constraint = tclass_datum->constraints; | 694 | constraint = tclass_datum->constraints; |
705 | while (constraint) { | 695 | while (constraint) { |
706 | if ((constraint->permissions & (avd->allowed)) && | 696 | if ((constraint->permissions & (avd->allowed)) && |
707 | !constraint_expr_eval(scontext, tcontext, NULL, | 697 | !constraint_expr_eval(policydb, scontext, tcontext, NULL, |
708 | constraint->expr)) { | 698 | constraint->expr)) { |
709 | avd->allowed &= ~(constraint->permissions); | 699 | avd->allowed &= ~(constraint->permissions); |
710 | } | 700 | } |
@@ -716,16 +706,16 @@ static void context_struct_compute_av(struct context *scontext, | |||
716 | * role is changing, then check the (current_role, new_role) | 706 | * role is changing, then check the (current_role, new_role) |
717 | * pair. | 707 | * pair. |
718 | */ | 708 | */ |
719 | if (tclass == policydb.process_class && | 709 | if (tclass == policydb->process_class && |
720 | (avd->allowed & policydb.process_trans_perms) && | 710 | (avd->allowed & policydb->process_trans_perms) && |
721 | scontext->role != tcontext->role) { | 711 | scontext->role != tcontext->role) { |
722 | for (ra = policydb.role_allow; ra; ra = ra->next) { | 712 | for (ra = policydb->role_allow; ra; ra = ra->next) { |
723 | if (scontext->role == ra->role && | 713 | if (scontext->role == ra->role && |
724 | tcontext->role == ra->new_role) | 714 | tcontext->role == ra->new_role) |
725 | break; | 715 | break; |
726 | } | 716 | } |
727 | if (!ra) | 717 | if (!ra) |
728 | avd->allowed &= ~policydb.process_trans_perms; | 718 | avd->allowed &= ~policydb->process_trans_perms; |
729 | } | 719 | } |
730 | 720 | ||
731 | /* | 721 | /* |
@@ -733,41 +723,46 @@ static void context_struct_compute_av(struct context *scontext, | |||
733 | * constraint, lazy checks have to mask any violated | 723 | * constraint, lazy checks have to mask any violated |
734 | * permission and notice it to userspace via audit. | 724 | * permission and notice it to userspace via audit. |
735 | */ | 725 | */ |
736 | type_attribute_bounds_av(scontext, tcontext, | 726 | type_attribute_bounds_av(policydb, scontext, tcontext, |
737 | tclass, avd); | 727 | tclass, avd); |
738 | } | 728 | } |
739 | 729 | ||
740 | static int security_validtrans_handle_fail(struct context *ocontext, | 730 | static int security_validtrans_handle_fail(struct selinux_state *state, |
731 | struct context *ocontext, | ||
741 | struct context *ncontext, | 732 | struct context *ncontext, |
742 | struct context *tcontext, | 733 | struct context *tcontext, |
743 | u16 tclass) | 734 | u16 tclass) |
744 | { | 735 | { |
736 | struct policydb *p = &state->ss->policydb; | ||
745 | char *o = NULL, *n = NULL, *t = NULL; | 737 | char *o = NULL, *n = NULL, *t = NULL; |
746 | u32 olen, nlen, tlen; | 738 | u32 olen, nlen, tlen; |
747 | 739 | ||
748 | if (context_struct_to_string(ocontext, &o, &olen)) | 740 | if (context_struct_to_string(p, ocontext, &o, &olen)) |
749 | goto out; | 741 | goto out; |
750 | if (context_struct_to_string(ncontext, &n, &nlen)) | 742 | if (context_struct_to_string(p, ncontext, &n, &nlen)) |
751 | goto out; | 743 | goto out; |
752 | if (context_struct_to_string(tcontext, &t, &tlen)) | 744 | if (context_struct_to_string(p, tcontext, &t, &tlen)) |
753 | goto out; | 745 | goto out; |
754 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 746 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
755 | "op=security_validate_transition seresult=denied" | 747 | "op=security_validate_transition seresult=denied" |
756 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", | 748 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", |
757 | o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); | 749 | o, n, t, sym_name(p, SYM_CLASSES, tclass-1)); |
758 | out: | 750 | out: |
759 | kfree(o); | 751 | kfree(o); |
760 | kfree(n); | 752 | kfree(n); |
761 | kfree(t); | 753 | kfree(t); |
762 | 754 | ||
763 | if (!selinux_enforcing) | 755 | if (!enforcing_enabled(state)) |
764 | return 0; | 756 | return 0; |
765 | return -EPERM; | 757 | return -EPERM; |
766 | } | 758 | } |
767 | 759 | ||
768 | static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | 760 | static int security_compute_validatetrans(struct selinux_state *state, |
761 | u32 oldsid, u32 newsid, u32 tasksid, | ||
769 | u16 orig_tclass, bool user) | 762 | u16 orig_tclass, bool user) |
770 | { | 763 | { |
764 | struct policydb *policydb; | ||
765 | struct sidtab *sidtab; | ||
771 | struct context *ocontext; | 766 | struct context *ocontext; |
772 | struct context *ncontext; | 767 | struct context *ncontext; |
773 | struct context *tcontext; | 768 | struct context *tcontext; |
@@ -776,23 +771,27 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | |||
776 | u16 tclass; | 771 | u16 tclass; |
777 | int rc = 0; | 772 | int rc = 0; |
778 | 773 | ||
779 | if (!ss_initialized) | 774 | |
775 | if (!state->initialized) | ||
780 | return 0; | 776 | return 0; |
781 | 777 | ||
782 | read_lock(&policy_rwlock); | 778 | read_lock(&state->ss->policy_rwlock); |
779 | |||
780 | policydb = &state->ss->policydb; | ||
781 | sidtab = &state->ss->sidtab; | ||
783 | 782 | ||
784 | if (!user) | 783 | if (!user) |
785 | tclass = unmap_class(orig_tclass); | 784 | tclass = unmap_class(&state->ss->map, orig_tclass); |
786 | else | 785 | else |
787 | tclass = orig_tclass; | 786 | tclass = orig_tclass; |
788 | 787 | ||
789 | if (!tclass || tclass > policydb.p_classes.nprim) { | 788 | if (!tclass || tclass > policydb->p_classes.nprim) { |
790 | rc = -EINVAL; | 789 | rc = -EINVAL; |
791 | goto out; | 790 | goto out; |
792 | } | 791 | } |
793 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 792 | tclass_datum = policydb->class_val_to_struct[tclass - 1]; |
794 | 793 | ||
795 | ocontext = sidtab_search(&sidtab, oldsid); | 794 | ocontext = sidtab_search(sidtab, oldsid); |
796 | if (!ocontext) { | 795 | if (!ocontext) { |
797 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 796 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
798 | __func__, oldsid); | 797 | __func__, oldsid); |
@@ -800,7 +799,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | |||
800 | goto out; | 799 | goto out; |
801 | } | 800 | } |
802 | 801 | ||
803 | ncontext = sidtab_search(&sidtab, newsid); | 802 | ncontext = sidtab_search(sidtab, newsid); |
804 | if (!ncontext) { | 803 | if (!ncontext) { |
805 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 804 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
806 | __func__, newsid); | 805 | __func__, newsid); |
@@ -808,7 +807,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | |||
808 | goto out; | 807 | goto out; |
809 | } | 808 | } |
810 | 809 | ||
811 | tcontext = sidtab_search(&sidtab, tasksid); | 810 | tcontext = sidtab_search(sidtab, tasksid); |
812 | if (!tcontext) { | 811 | if (!tcontext) { |
813 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 812 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
814 | __func__, tasksid); | 813 | __func__, tasksid); |
@@ -818,12 +817,13 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | |||
818 | 817 | ||
819 | constraint = tclass_datum->validatetrans; | 818 | constraint = tclass_datum->validatetrans; |
820 | while (constraint) { | 819 | while (constraint) { |
821 | if (!constraint_expr_eval(ocontext, ncontext, tcontext, | 820 | if (!constraint_expr_eval(policydb, ocontext, ncontext, |
822 | constraint->expr)) { | 821 | tcontext, constraint->expr)) { |
823 | if (user) | 822 | if (user) |
824 | rc = -EPERM; | 823 | rc = -EPERM; |
825 | else | 824 | else |
826 | rc = security_validtrans_handle_fail(ocontext, | 825 | rc = security_validtrans_handle_fail(state, |
826 | ocontext, | ||
827 | ncontext, | 827 | ncontext, |
828 | tcontext, | 828 | tcontext, |
829 | tclass); | 829 | tclass); |
@@ -833,22 +833,24 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, | |||
833 | } | 833 | } |
834 | 834 | ||
835 | out: | 835 | out: |
836 | read_unlock(&policy_rwlock); | 836 | read_unlock(&state->ss->policy_rwlock); |
837 | return rc; | 837 | return rc; |
838 | } | 838 | } |
839 | 839 | ||
840 | int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid, | 840 | int security_validate_transition_user(struct selinux_state *state, |
841 | u16 tclass) | 841 | u32 oldsid, u32 newsid, u32 tasksid, |
842 | u16 tclass) | ||
842 | { | 843 | { |
843 | return security_compute_validatetrans(oldsid, newsid, tasksid, | 844 | return security_compute_validatetrans(state, oldsid, newsid, tasksid, |
844 | tclass, true); | 845 | tclass, true); |
845 | } | 846 | } |
846 | 847 | ||
847 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 848 | int security_validate_transition(struct selinux_state *state, |
849 | u32 oldsid, u32 newsid, u32 tasksid, | ||
848 | u16 orig_tclass) | 850 | u16 orig_tclass) |
849 | { | 851 | { |
850 | return security_compute_validatetrans(oldsid, newsid, tasksid, | 852 | return security_compute_validatetrans(state, oldsid, newsid, tasksid, |
851 | orig_tclass, false); | 853 | orig_tclass, false); |
852 | } | 854 | } |
853 | 855 | ||
854 | /* | 856 | /* |
@@ -860,20 +862,26 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
860 | * @oldsid : current security identifier | 862 | * @oldsid : current security identifier |
861 | * @newsid : destinated security identifier | 863 | * @newsid : destinated security identifier |
862 | */ | 864 | */ |
863 | int security_bounded_transition(u32 old_sid, u32 new_sid) | 865 | int security_bounded_transition(struct selinux_state *state, |
866 | u32 old_sid, u32 new_sid) | ||
864 | { | 867 | { |
868 | struct policydb *policydb; | ||
869 | struct sidtab *sidtab; | ||
865 | struct context *old_context, *new_context; | 870 | struct context *old_context, *new_context; |
866 | struct type_datum *type; | 871 | struct type_datum *type; |
867 | int index; | 872 | int index; |
868 | int rc; | 873 | int rc; |
869 | 874 | ||
870 | if (!ss_initialized) | 875 | if (!state->initialized) |
871 | return 0; | 876 | return 0; |
872 | 877 | ||
873 | read_lock(&policy_rwlock); | 878 | read_lock(&state->ss->policy_rwlock); |
879 | |||
880 | policydb = &state->ss->policydb; | ||
881 | sidtab = &state->ss->sidtab; | ||
874 | 882 | ||
875 | rc = -EINVAL; | 883 | rc = -EINVAL; |
876 | old_context = sidtab_search(&sidtab, old_sid); | 884 | old_context = sidtab_search(sidtab, old_sid); |
877 | if (!old_context) { | 885 | if (!old_context) { |
878 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", | 886 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", |
879 | __func__, old_sid); | 887 | __func__, old_sid); |
@@ -881,7 +889,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
881 | } | 889 | } |
882 | 890 | ||
883 | rc = -EINVAL; | 891 | rc = -EINVAL; |
884 | new_context = sidtab_search(&sidtab, new_sid); | 892 | new_context = sidtab_search(sidtab, new_sid); |
885 | if (!new_context) { | 893 | if (!new_context) { |
886 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", | 894 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", |
887 | __func__, new_sid); | 895 | __func__, new_sid); |
@@ -895,7 +903,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
895 | 903 | ||
896 | index = new_context->type; | 904 | index = new_context->type; |
897 | while (true) { | 905 | while (true) { |
898 | type = flex_array_get_ptr(policydb.type_val_to_struct_array, | 906 | type = flex_array_get_ptr(policydb->type_val_to_struct_array, |
899 | index - 1); | 907 | index - 1); |
900 | BUG_ON(!type); | 908 | BUG_ON(!type); |
901 | 909 | ||
@@ -917,9 +925,9 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
917 | char *new_name = NULL; | 925 | char *new_name = NULL; |
918 | u32 length; | 926 | u32 length; |
919 | 927 | ||
920 | if (!context_struct_to_string(old_context, | 928 | if (!context_struct_to_string(policydb, old_context, |
921 | &old_name, &length) && | 929 | &old_name, &length) && |
922 | !context_struct_to_string(new_context, | 930 | !context_struct_to_string(policydb, new_context, |
923 | &new_name, &length)) { | 931 | &new_name, &length)) { |
924 | audit_log(current->audit_context, | 932 | audit_log(current->audit_context, |
925 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | 933 | GFP_ATOMIC, AUDIT_SELINUX_ERR, |
@@ -932,17 +940,17 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
932 | kfree(old_name); | 940 | kfree(old_name); |
933 | } | 941 | } |
934 | out: | 942 | out: |
935 | read_unlock(&policy_rwlock); | 943 | read_unlock(&state->ss->policy_rwlock); |
936 | 944 | ||
937 | return rc; | 945 | return rc; |
938 | } | 946 | } |
939 | 947 | ||
940 | static void avd_init(struct av_decision *avd) | 948 | static void avd_init(struct selinux_state *state, struct av_decision *avd) |
941 | { | 949 | { |
942 | avd->allowed = 0; | 950 | avd->allowed = 0; |
943 | avd->auditallow = 0; | 951 | avd->auditallow = 0; |
944 | avd->auditdeny = 0xffffffff; | 952 | avd->auditdeny = 0xffffffff; |
945 | avd->seqno = latest_granting; | 953 | avd->seqno = state->ss->latest_granting; |
946 | avd->flags = 0; | 954 | avd->flags = 0; |
947 | } | 955 | } |
948 | 956 | ||
@@ -1000,12 +1008,15 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, | |||
1000 | } | 1008 | } |
1001 | } | 1009 | } |
1002 | 1010 | ||
1003 | void security_compute_xperms_decision(u32 ssid, | 1011 | void security_compute_xperms_decision(struct selinux_state *state, |
1004 | u32 tsid, | 1012 | u32 ssid, |
1005 | u16 orig_tclass, | 1013 | u32 tsid, |
1006 | u8 driver, | 1014 | u16 orig_tclass, |
1007 | struct extended_perms_decision *xpermd) | 1015 | u8 driver, |
1016 | struct extended_perms_decision *xpermd) | ||
1008 | { | 1017 | { |
1018 | struct policydb *policydb; | ||
1019 | struct sidtab *sidtab; | ||
1009 | u16 tclass; | 1020 | u16 tclass; |
1010 | struct context *scontext, *tcontext; | 1021 | struct context *scontext, *tcontext; |
1011 | struct avtab_key avkey; | 1022 | struct avtab_key avkey; |
@@ -1020,60 +1031,64 @@ void security_compute_xperms_decision(u32 ssid, | |||
1020 | memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p)); | 1031 | memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p)); |
1021 | memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p)); | 1032 | memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p)); |
1022 | 1033 | ||
1023 | read_lock(&policy_rwlock); | 1034 | read_lock(&state->ss->policy_rwlock); |
1024 | if (!ss_initialized) | 1035 | if (!state->initialized) |
1025 | goto allow; | 1036 | goto allow; |
1026 | 1037 | ||
1027 | scontext = sidtab_search(&sidtab, ssid); | 1038 | policydb = &state->ss->policydb; |
1039 | sidtab = &state->ss->sidtab; | ||
1040 | |||
1041 | scontext = sidtab_search(sidtab, ssid); | ||
1028 | if (!scontext) { | 1042 | if (!scontext) { |
1029 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1043 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1030 | __func__, ssid); | 1044 | __func__, ssid); |
1031 | goto out; | 1045 | goto out; |
1032 | } | 1046 | } |
1033 | 1047 | ||
1034 | tcontext = sidtab_search(&sidtab, tsid); | 1048 | tcontext = sidtab_search(sidtab, tsid); |
1035 | if (!tcontext) { | 1049 | if (!tcontext) { |
1036 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1050 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1037 | __func__, tsid); | 1051 | __func__, tsid); |
1038 | goto out; | 1052 | goto out; |
1039 | } | 1053 | } |
1040 | 1054 | ||
1041 | tclass = unmap_class(orig_tclass); | 1055 | tclass = unmap_class(&state->ss->map, orig_tclass); |
1042 | if (unlikely(orig_tclass && !tclass)) { | 1056 | if (unlikely(orig_tclass && !tclass)) { |
1043 | if (policydb.allow_unknown) | 1057 | if (policydb->allow_unknown) |
1044 | goto allow; | 1058 | goto allow; |
1045 | goto out; | 1059 | goto out; |
1046 | } | 1060 | } |
1047 | 1061 | ||
1048 | 1062 | ||
1049 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { | 1063 | if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { |
1050 | pr_warn_ratelimited("SELinux: Invalid class %hu\n", tclass); | 1064 | pr_warn_ratelimited("SELinux: Invalid class %hu\n", tclass); |
1051 | goto out; | 1065 | goto out; |
1052 | } | 1066 | } |
1053 | 1067 | ||
1054 | avkey.target_class = tclass; | 1068 | avkey.target_class = tclass; |
1055 | avkey.specified = AVTAB_XPERMS; | 1069 | avkey.specified = AVTAB_XPERMS; |
1056 | sattr = flex_array_get(policydb.type_attr_map_array, | 1070 | sattr = flex_array_get(policydb->type_attr_map_array, |
1057 | scontext->type - 1); | 1071 | scontext->type - 1); |
1058 | BUG_ON(!sattr); | 1072 | BUG_ON(!sattr); |
1059 | tattr = flex_array_get(policydb.type_attr_map_array, | 1073 | tattr = flex_array_get(policydb->type_attr_map_array, |
1060 | tcontext->type - 1); | 1074 | tcontext->type - 1); |
1061 | BUG_ON(!tattr); | 1075 | BUG_ON(!tattr); |
1062 | ebitmap_for_each_positive_bit(sattr, snode, i) { | 1076 | ebitmap_for_each_positive_bit(sattr, snode, i) { |
1063 | ebitmap_for_each_positive_bit(tattr, tnode, j) { | 1077 | ebitmap_for_each_positive_bit(tattr, tnode, j) { |
1064 | avkey.source_type = i + 1; | 1078 | avkey.source_type = i + 1; |
1065 | avkey.target_type = j + 1; | 1079 | avkey.target_type = j + 1; |
1066 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | 1080 | for (node = avtab_search_node(&policydb->te_avtab, |
1081 | &avkey); | ||
1067 | node; | 1082 | node; |
1068 | node = avtab_search_node_next(node, avkey.specified)) | 1083 | node = avtab_search_node_next(node, avkey.specified)) |
1069 | services_compute_xperms_decision(xpermd, node); | 1084 | services_compute_xperms_decision(xpermd, node); |
1070 | 1085 | ||
1071 | cond_compute_xperms(&policydb.te_cond_avtab, | 1086 | cond_compute_xperms(&policydb->te_cond_avtab, |
1072 | &avkey, xpermd); | 1087 | &avkey, xpermd); |
1073 | } | 1088 | } |
1074 | } | 1089 | } |
1075 | out: | 1090 | out: |
1076 | read_unlock(&policy_rwlock); | 1091 | read_unlock(&state->ss->policy_rwlock); |
1077 | return; | 1092 | return; |
1078 | allow: | 1093 | allow: |
1079 | memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p)); | 1094 | memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p)); |
@@ -1091,22 +1106,28 @@ allow: | |||
1091 | * Compute a set of access vector decisions based on the | 1106 | * Compute a set of access vector decisions based on the |
1092 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 1107 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
1093 | */ | 1108 | */ |
1094 | void security_compute_av(u32 ssid, | 1109 | void security_compute_av(struct selinux_state *state, |
1110 | u32 ssid, | ||
1095 | u32 tsid, | 1111 | u32 tsid, |
1096 | u16 orig_tclass, | 1112 | u16 orig_tclass, |
1097 | struct av_decision *avd, | 1113 | struct av_decision *avd, |
1098 | struct extended_perms *xperms) | 1114 | struct extended_perms *xperms) |
1099 | { | 1115 | { |
1116 | struct policydb *policydb; | ||
1117 | struct sidtab *sidtab; | ||
1100 | u16 tclass; | 1118 | u16 tclass; |
1101 | struct context *scontext = NULL, *tcontext = NULL; | 1119 | struct context *scontext = NULL, *tcontext = NULL; |
1102 | 1120 | ||
1103 | read_lock(&policy_rwlock); | 1121 | read_lock(&state->ss->policy_rwlock); |
1104 | avd_init(avd); | 1122 | avd_init(state, avd); |
1105 | xperms->len = 0; | 1123 | xperms->len = 0; |
1106 | if (!ss_initialized) | 1124 | if (!state->initialized) |
1107 | goto allow; | 1125 | goto allow; |
1108 | 1126 | ||
1109 | scontext = sidtab_search(&sidtab, ssid); | 1127 | policydb = &state->ss->policydb; |
1128 | sidtab = &state->ss->sidtab; | ||
1129 | |||
1130 | scontext = sidtab_search(sidtab, ssid); | ||
1110 | if (!scontext) { | 1131 | if (!scontext) { |
1111 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1132 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1112 | __func__, ssid); | 1133 | __func__, ssid); |
@@ -1114,45 +1135,53 @@ void security_compute_av(u32 ssid, | |||
1114 | } | 1135 | } |
1115 | 1136 | ||
1116 | /* permissive domain? */ | 1137 | /* permissive domain? */ |
1117 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | 1138 | if (ebitmap_get_bit(&policydb->permissive_map, scontext->type)) |
1118 | avd->flags |= AVD_FLAGS_PERMISSIVE; | 1139 | avd->flags |= AVD_FLAGS_PERMISSIVE; |
1119 | 1140 | ||
1120 | tcontext = sidtab_search(&sidtab, tsid); | 1141 | tcontext = sidtab_search(sidtab, tsid); |
1121 | if (!tcontext) { | 1142 | if (!tcontext) { |
1122 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1143 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1123 | __func__, tsid); | 1144 | __func__, tsid); |
1124 | goto out; | 1145 | goto out; |
1125 | } | 1146 | } |
1126 | 1147 | ||
1127 | tclass = unmap_class(orig_tclass); | 1148 | tclass = unmap_class(&state->ss->map, orig_tclass); |
1128 | if (unlikely(orig_tclass && !tclass)) { | 1149 | if (unlikely(orig_tclass && !tclass)) { |
1129 | if (policydb.allow_unknown) | 1150 | if (policydb->allow_unknown) |
1130 | goto allow; | 1151 | goto allow; |
1131 | goto out; | 1152 | goto out; |
1132 | } | 1153 | } |
1133 | context_struct_compute_av(scontext, tcontext, tclass, avd, xperms); | 1154 | context_struct_compute_av(policydb, scontext, tcontext, tclass, avd, |
1134 | map_decision(orig_tclass, avd, policydb.allow_unknown); | 1155 | xperms); |
1156 | map_decision(&state->ss->map, orig_tclass, avd, | ||
1157 | policydb->allow_unknown); | ||
1135 | out: | 1158 | out: |
1136 | read_unlock(&policy_rwlock); | 1159 | read_unlock(&state->ss->policy_rwlock); |
1137 | return; | 1160 | return; |
1138 | allow: | 1161 | allow: |
1139 | avd->allowed = 0xffffffff; | 1162 | avd->allowed = 0xffffffff; |
1140 | goto out; | 1163 | goto out; |
1141 | } | 1164 | } |
1142 | 1165 | ||
1143 | void security_compute_av_user(u32 ssid, | 1166 | void security_compute_av_user(struct selinux_state *state, |
1167 | u32 ssid, | ||
1144 | u32 tsid, | 1168 | u32 tsid, |
1145 | u16 tclass, | 1169 | u16 tclass, |
1146 | struct av_decision *avd) | 1170 | struct av_decision *avd) |
1147 | { | 1171 | { |
1172 | struct policydb *policydb; | ||
1173 | struct sidtab *sidtab; | ||
1148 | struct context *scontext = NULL, *tcontext = NULL; | 1174 | struct context *scontext = NULL, *tcontext = NULL; |
1149 | 1175 | ||
1150 | read_lock(&policy_rwlock); | 1176 | read_lock(&state->ss->policy_rwlock); |
1151 | avd_init(avd); | 1177 | avd_init(state, avd); |
1152 | if (!ss_initialized) | 1178 | if (!state->initialized) |
1153 | goto allow; | 1179 | goto allow; |
1154 | 1180 | ||
1155 | scontext = sidtab_search(&sidtab, ssid); | 1181 | policydb = &state->ss->policydb; |
1182 | sidtab = &state->ss->sidtab; | ||
1183 | |||
1184 | scontext = sidtab_search(sidtab, ssid); | ||
1156 | if (!scontext) { | 1185 | if (!scontext) { |
1157 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1186 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1158 | __func__, ssid); | 1187 | __func__, ssid); |
@@ -1160,10 +1189,10 @@ void security_compute_av_user(u32 ssid, | |||
1160 | } | 1189 | } |
1161 | 1190 | ||
1162 | /* permissive domain? */ | 1191 | /* permissive domain? */ |
1163 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | 1192 | if (ebitmap_get_bit(&policydb->permissive_map, scontext->type)) |
1164 | avd->flags |= AVD_FLAGS_PERMISSIVE; | 1193 | avd->flags |= AVD_FLAGS_PERMISSIVE; |
1165 | 1194 | ||
1166 | tcontext = sidtab_search(&sidtab, tsid); | 1195 | tcontext = sidtab_search(sidtab, tsid); |
1167 | if (!tcontext) { | 1196 | if (!tcontext) { |
1168 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1197 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1169 | __func__, tsid); | 1198 | __func__, tsid); |
@@ -1171,14 +1200,15 @@ void security_compute_av_user(u32 ssid, | |||
1171 | } | 1200 | } |
1172 | 1201 | ||
1173 | if (unlikely(!tclass)) { | 1202 | if (unlikely(!tclass)) { |
1174 | if (policydb.allow_unknown) | 1203 | if (policydb->allow_unknown) |
1175 | goto allow; | 1204 | goto allow; |
1176 | goto out; | 1205 | goto out; |
1177 | } | 1206 | } |
1178 | 1207 | ||
1179 | context_struct_compute_av(scontext, tcontext, tclass, avd, NULL); | 1208 | context_struct_compute_av(policydb, scontext, tcontext, tclass, avd, |
1209 | NULL); | ||
1180 | out: | 1210 | out: |
1181 | read_unlock(&policy_rwlock); | 1211 | read_unlock(&state->ss->policy_rwlock); |
1182 | return; | 1212 | return; |
1183 | allow: | 1213 | allow: |
1184 | avd->allowed = 0xffffffff; | 1214 | avd->allowed = 0xffffffff; |
@@ -1192,7 +1222,9 @@ allow: | |||
1192 | * to point to this string and set `*scontext_len' to | 1222 | * to point to this string and set `*scontext_len' to |
1193 | * the length of the string. | 1223 | * the length of the string. |
1194 | */ | 1224 | */ |
1195 | static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len) | 1225 | static int context_struct_to_string(struct policydb *p, |
1226 | struct context *context, | ||
1227 | char **scontext, u32 *scontext_len) | ||
1196 | { | 1228 | { |
1197 | char *scontextp; | 1229 | char *scontextp; |
1198 | 1230 | ||
@@ -1211,10 +1243,10 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
1211 | } | 1243 | } |
1212 | 1244 | ||
1213 | /* Compute the size of the context. */ | 1245 | /* Compute the size of the context. */ |
1214 | *scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1; | 1246 | *scontext_len += strlen(sym_name(p, SYM_USERS, context->user - 1)) + 1; |
1215 | *scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1; | 1247 | *scontext_len += strlen(sym_name(p, SYM_ROLES, context->role - 1)) + 1; |
1216 | *scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1; | 1248 | *scontext_len += strlen(sym_name(p, SYM_TYPES, context->type - 1)) + 1; |
1217 | *scontext_len += mls_compute_context_len(context); | 1249 | *scontext_len += mls_compute_context_len(p, context); |
1218 | 1250 | ||
1219 | if (!scontext) | 1251 | if (!scontext) |
1220 | return 0; | 1252 | return 0; |
@@ -1229,11 +1261,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
1229 | * Copy the user name, role name and type name into the context. | 1261 | * Copy the user name, role name and type name into the context. |
1230 | */ | 1262 | */ |
1231 | scontextp += sprintf(scontextp, "%s:%s:%s", | 1263 | scontextp += sprintf(scontextp, "%s:%s:%s", |
1232 | sym_name(&policydb, SYM_USERS, context->user - 1), | 1264 | sym_name(p, SYM_USERS, context->user - 1), |
1233 | sym_name(&policydb, SYM_ROLES, context->role - 1), | 1265 | sym_name(p, SYM_ROLES, context->role - 1), |
1234 | sym_name(&policydb, SYM_TYPES, context->type - 1)); | 1266 | sym_name(p, SYM_TYPES, context->type - 1)); |
1235 | 1267 | ||
1236 | mls_sid_to_context(context, &scontextp); | 1268 | mls_sid_to_context(p, context, &scontextp); |
1237 | 1269 | ||
1238 | *scontextp = 0; | 1270 | *scontextp = 0; |
1239 | 1271 | ||
@@ -1249,9 +1281,12 @@ const char *security_get_initial_sid_context(u32 sid) | |||
1249 | return initial_sid_to_string[sid]; | 1281 | return initial_sid_to_string[sid]; |
1250 | } | 1282 | } |
1251 | 1283 | ||
1252 | static int security_sid_to_context_core(u32 sid, char **scontext, | 1284 | static int security_sid_to_context_core(struct selinux_state *state, |
1285 | u32 sid, char **scontext, | ||
1253 | u32 *scontext_len, int force) | 1286 | u32 *scontext_len, int force) |
1254 | { | 1287 | { |
1288 | struct policydb *policydb; | ||
1289 | struct sidtab *sidtab; | ||
1255 | struct context *context; | 1290 | struct context *context; |
1256 | int rc = 0; | 1291 | int rc = 0; |
1257 | 1292 | ||
@@ -1259,7 +1294,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
1259 | *scontext = NULL; | 1294 | *scontext = NULL; |
1260 | *scontext_len = 0; | 1295 | *scontext_len = 0; |
1261 | 1296 | ||
1262 | if (!ss_initialized) { | 1297 | if (!state->initialized) { |
1263 | if (sid <= SECINITSID_NUM) { | 1298 | if (sid <= SECINITSID_NUM) { |
1264 | char *scontextp; | 1299 | char *scontextp; |
1265 | 1300 | ||
@@ -1280,20 +1315,23 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
1280 | rc = -EINVAL; | 1315 | rc = -EINVAL; |
1281 | goto out; | 1316 | goto out; |
1282 | } | 1317 | } |
1283 | read_lock(&policy_rwlock); | 1318 | read_lock(&state->ss->policy_rwlock); |
1319 | policydb = &state->ss->policydb; | ||
1320 | sidtab = &state->ss->sidtab; | ||
1284 | if (force) | 1321 | if (force) |
1285 | context = sidtab_search_force(&sidtab, sid); | 1322 | context = sidtab_search_force(sidtab, sid); |
1286 | else | 1323 | else |
1287 | context = sidtab_search(&sidtab, sid); | 1324 | context = sidtab_search(sidtab, sid); |
1288 | if (!context) { | 1325 | if (!context) { |
1289 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1326 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1290 | __func__, sid); | 1327 | __func__, sid); |
1291 | rc = -EINVAL; | 1328 | rc = -EINVAL; |
1292 | goto out_unlock; | 1329 | goto out_unlock; |
1293 | } | 1330 | } |
1294 | rc = context_struct_to_string(context, scontext, scontext_len); | 1331 | rc = context_struct_to_string(policydb, context, scontext, |
1332 | scontext_len); | ||
1295 | out_unlock: | 1333 | out_unlock: |
1296 | read_unlock(&policy_rwlock); | 1334 | read_unlock(&state->ss->policy_rwlock); |
1297 | out: | 1335 | out: |
1298 | return rc; | 1336 | return rc; |
1299 | 1337 | ||
@@ -1309,14 +1347,18 @@ out: | |||
1309 | * into a dynamically allocated string of the correct size. Set @scontext | 1347 | * into a dynamically allocated string of the correct size. Set @scontext |
1310 | * to point to this string and set @scontext_len to the length of the string. | 1348 | * to point to this string and set @scontext_len to the length of the string. |
1311 | */ | 1349 | */ |
1312 | int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) | 1350 | int security_sid_to_context(struct selinux_state *state, |
1351 | u32 sid, char **scontext, u32 *scontext_len) | ||
1313 | { | 1352 | { |
1314 | return security_sid_to_context_core(sid, scontext, scontext_len, 0); | 1353 | return security_sid_to_context_core(state, sid, scontext, |
1354 | scontext_len, 0); | ||
1315 | } | 1355 | } |
1316 | 1356 | ||
1317 | int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len) | 1357 | int security_sid_to_context_force(struct selinux_state *state, u32 sid, |
1358 | char **scontext, u32 *scontext_len) | ||
1318 | { | 1359 | { |
1319 | return security_sid_to_context_core(sid, scontext, scontext_len, 1); | 1360 | return security_sid_to_context_core(state, sid, scontext, |
1361 | scontext_len, 1); | ||
1320 | } | 1362 | } |
1321 | 1363 | ||
1322 | /* | 1364 | /* |
@@ -1404,10 +1446,13 @@ out: | |||
1404 | return rc; | 1446 | return rc; |
1405 | } | 1447 | } |
1406 | 1448 | ||
1407 | static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | 1449 | static int security_context_to_sid_core(struct selinux_state *state, |
1450 | const char *scontext, u32 scontext_len, | ||
1408 | u32 *sid, u32 def_sid, gfp_t gfp_flags, | 1451 | u32 *sid, u32 def_sid, gfp_t gfp_flags, |
1409 | int force) | 1452 | int force) |
1410 | { | 1453 | { |
1454 | struct policydb *policydb; | ||
1455 | struct sidtab *sidtab; | ||
1411 | char *scontext2, *str = NULL; | 1456 | char *scontext2, *str = NULL; |
1412 | struct context context; | 1457 | struct context context; |
1413 | int rc = 0; | 1458 | int rc = 0; |
@@ -1421,7 +1466,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
1421 | if (!scontext2) | 1466 | if (!scontext2) |
1422 | return -ENOMEM; | 1467 | return -ENOMEM; |
1423 | 1468 | ||
1424 | if (!ss_initialized) { | 1469 | if (!state->initialized) { |
1425 | int i; | 1470 | int i; |
1426 | 1471 | ||
1427 | for (i = 1; i < SECINITSID_NUM; i++) { | 1472 | for (i = 1; i < SECINITSID_NUM; i++) { |
@@ -1442,9 +1487,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
1442 | if (!str) | 1487 | if (!str) |
1443 | goto out; | 1488 | goto out; |
1444 | } | 1489 | } |
1445 | 1490 | read_lock(&state->ss->policy_rwlock); | |
1446 | read_lock(&policy_rwlock); | 1491 | policydb = &state->ss->policydb; |
1447 | rc = string_to_context_struct(&policydb, &sidtab, scontext2, | 1492 | sidtab = &state->ss->sidtab; |
1493 | rc = string_to_context_struct(policydb, sidtab, scontext2, | ||
1448 | scontext_len, &context, def_sid); | 1494 | scontext_len, &context, def_sid); |
1449 | if (rc == -EINVAL && force) { | 1495 | if (rc == -EINVAL && force) { |
1450 | context.str = str; | 1496 | context.str = str; |
@@ -1452,10 +1498,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
1452 | str = NULL; | 1498 | str = NULL; |
1453 | } else if (rc) | 1499 | } else if (rc) |
1454 | goto out_unlock; | 1500 | goto out_unlock; |
1455 | rc = sidtab_context_to_sid(&sidtab, &context, sid); | 1501 | rc = sidtab_context_to_sid(sidtab, &context, sid); |
1456 | context_destroy(&context); | 1502 | context_destroy(&context); |
1457 | out_unlock: | 1503 | out_unlock: |
1458 | read_unlock(&policy_rwlock); | 1504 | read_unlock(&state->ss->policy_rwlock); |
1459 | out: | 1505 | out: |
1460 | kfree(scontext2); | 1506 | kfree(scontext2); |
1461 | kfree(str); | 1507 | kfree(str); |
@@ -1474,16 +1520,19 @@ out: | |||
1474 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | 1520 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient |
1475 | * memory is available, or 0 on success. | 1521 | * memory is available, or 0 on success. |
1476 | */ | 1522 | */ |
1477 | int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid, | 1523 | int security_context_to_sid(struct selinux_state *state, |
1524 | const char *scontext, u32 scontext_len, u32 *sid, | ||
1478 | gfp_t gfp) | 1525 | gfp_t gfp) |
1479 | { | 1526 | { |
1480 | return security_context_to_sid_core(scontext, scontext_len, | 1527 | return security_context_to_sid_core(state, scontext, scontext_len, |
1481 | sid, SECSID_NULL, gfp, 0); | 1528 | sid, SECSID_NULL, gfp, 0); |
1482 | } | 1529 | } |
1483 | 1530 | ||
1484 | int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp) | 1531 | int security_context_str_to_sid(struct selinux_state *state, |
1532 | const char *scontext, u32 *sid, gfp_t gfp) | ||
1485 | { | 1533 | { |
1486 | return security_context_to_sid(scontext, strlen(scontext), sid, gfp); | 1534 | return security_context_to_sid(state, scontext, strlen(scontext), |
1535 | sid, gfp); | ||
1487 | } | 1536 | } |
1488 | 1537 | ||
1489 | /** | 1538 | /** |
@@ -1504,51 +1553,56 @@ int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp) | |||
1504 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | 1553 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient |
1505 | * memory is available, or 0 on success. | 1554 | * memory is available, or 0 on success. |
1506 | */ | 1555 | */ |
1507 | int security_context_to_sid_default(const char *scontext, u32 scontext_len, | 1556 | int security_context_to_sid_default(struct selinux_state *state, |
1557 | const char *scontext, u32 scontext_len, | ||
1508 | u32 *sid, u32 def_sid, gfp_t gfp_flags) | 1558 | u32 *sid, u32 def_sid, gfp_t gfp_flags) |
1509 | { | 1559 | { |
1510 | return security_context_to_sid_core(scontext, scontext_len, | 1560 | return security_context_to_sid_core(state, scontext, scontext_len, |
1511 | sid, def_sid, gfp_flags, 1); | 1561 | sid, def_sid, gfp_flags, 1); |
1512 | } | 1562 | } |
1513 | 1563 | ||
1514 | int security_context_to_sid_force(const char *scontext, u32 scontext_len, | 1564 | int security_context_to_sid_force(struct selinux_state *state, |
1565 | const char *scontext, u32 scontext_len, | ||
1515 | u32 *sid) | 1566 | u32 *sid) |
1516 | { | 1567 | { |
1517 | return security_context_to_sid_core(scontext, scontext_len, | 1568 | return security_context_to_sid_core(state, scontext, scontext_len, |
1518 | sid, SECSID_NULL, GFP_KERNEL, 1); | 1569 | sid, SECSID_NULL, GFP_KERNEL, 1); |
1519 | } | 1570 | } |
1520 | 1571 | ||
1521 | static int compute_sid_handle_invalid_context( | 1572 | static int compute_sid_handle_invalid_context( |
1573 | struct selinux_state *state, | ||
1522 | struct context *scontext, | 1574 | struct context *scontext, |
1523 | struct context *tcontext, | 1575 | struct context *tcontext, |
1524 | u16 tclass, | 1576 | u16 tclass, |
1525 | struct context *newcontext) | 1577 | struct context *newcontext) |
1526 | { | 1578 | { |
1579 | struct policydb *policydb = &state->ss->policydb; | ||
1527 | char *s = NULL, *t = NULL, *n = NULL; | 1580 | char *s = NULL, *t = NULL, *n = NULL; |
1528 | u32 slen, tlen, nlen; | 1581 | u32 slen, tlen, nlen; |
1529 | 1582 | ||
1530 | if (context_struct_to_string(scontext, &s, &slen)) | 1583 | if (context_struct_to_string(policydb, scontext, &s, &slen)) |
1531 | goto out; | 1584 | goto out; |
1532 | if (context_struct_to_string(tcontext, &t, &tlen)) | 1585 | if (context_struct_to_string(policydb, tcontext, &t, &tlen)) |
1533 | goto out; | 1586 | goto out; |
1534 | if (context_struct_to_string(newcontext, &n, &nlen)) | 1587 | if (context_struct_to_string(policydb, newcontext, &n, &nlen)) |
1535 | goto out; | 1588 | goto out; |
1536 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 1589 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
1537 | "op=security_compute_sid invalid_context=%s" | 1590 | "op=security_compute_sid invalid_context=%s" |
1538 | " scontext=%s" | 1591 | " scontext=%s" |
1539 | " tcontext=%s" | 1592 | " tcontext=%s" |
1540 | " tclass=%s", | 1593 | " tclass=%s", |
1541 | n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); | 1594 | n, s, t, sym_name(policydb, SYM_CLASSES, tclass-1)); |
1542 | out: | 1595 | out: |
1543 | kfree(s); | 1596 | kfree(s); |
1544 | kfree(t); | 1597 | kfree(t); |
1545 | kfree(n); | 1598 | kfree(n); |
1546 | if (!selinux_enforcing) | 1599 | if (!enforcing_enabled(state)) |
1547 | return 0; | 1600 | return 0; |
1548 | return -EACCES; | 1601 | return -EACCES; |
1549 | } | 1602 | } |
1550 | 1603 | ||
1551 | static void filename_compute_type(struct policydb *p, struct context *newcontext, | 1604 | static void filename_compute_type(struct policydb *policydb, |
1605 | struct context *newcontext, | ||
1552 | u32 stype, u32 ttype, u16 tclass, | 1606 | u32 stype, u32 ttype, u16 tclass, |
1553 | const char *objname) | 1607 | const char *objname) |
1554 | { | 1608 | { |
@@ -1560,7 +1614,7 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext | |||
1560 | * like /dev or /var/run. This bitmap will quickly skip rule searches | 1614 | * like /dev or /var/run. This bitmap will quickly skip rule searches |
1561 | * if the ttype does not contain any rules. | 1615 | * if the ttype does not contain any rules. |
1562 | */ | 1616 | */ |
1563 | if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) | 1617 | if (!ebitmap_get_bit(&policydb->filename_trans_ttypes, ttype)) |
1564 | return; | 1618 | return; |
1565 | 1619 | ||
1566 | ft.stype = stype; | 1620 | ft.stype = stype; |
@@ -1568,12 +1622,13 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext | |||
1568 | ft.tclass = tclass; | 1622 | ft.tclass = tclass; |
1569 | ft.name = objname; | 1623 | ft.name = objname; |
1570 | 1624 | ||
1571 | otype = hashtab_search(p->filename_trans, &ft); | 1625 | otype = hashtab_search(policydb->filename_trans, &ft); |
1572 | if (otype) | 1626 | if (otype) |
1573 | newcontext->type = otype->otype; | 1627 | newcontext->type = otype->otype; |
1574 | } | 1628 | } |
1575 | 1629 | ||
1576 | static int security_compute_sid(u32 ssid, | 1630 | static int security_compute_sid(struct selinux_state *state, |
1631 | u32 ssid, | ||
1577 | u32 tsid, | 1632 | u32 tsid, |
1578 | u16 orig_tclass, | 1633 | u16 orig_tclass, |
1579 | u32 specified, | 1634 | u32 specified, |
@@ -1581,6 +1636,8 @@ static int security_compute_sid(u32 ssid, | |||
1581 | u32 *out_sid, | 1636 | u32 *out_sid, |
1582 | bool kern) | 1637 | bool kern) |
1583 | { | 1638 | { |
1639 | struct policydb *policydb; | ||
1640 | struct sidtab *sidtab; | ||
1584 | struct class_datum *cladatum = NULL; | 1641 | struct class_datum *cladatum = NULL; |
1585 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1642 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1586 | struct role_trans *roletr = NULL; | 1643 | struct role_trans *roletr = NULL; |
@@ -1591,7 +1648,7 @@ static int security_compute_sid(u32 ssid, | |||
1591 | int rc = 0; | 1648 | int rc = 0; |
1592 | bool sock; | 1649 | bool sock; |
1593 | 1650 | ||
1594 | if (!ss_initialized) { | 1651 | if (!state->initialized) { |
1595 | switch (orig_tclass) { | 1652 | switch (orig_tclass) { |
1596 | case SECCLASS_PROCESS: /* kernel value */ | 1653 | case SECCLASS_PROCESS: /* kernel value */ |
1597 | *out_sid = ssid; | 1654 | *out_sid = ssid; |
@@ -1605,24 +1662,28 @@ static int security_compute_sid(u32 ssid, | |||
1605 | 1662 | ||
1606 | context_init(&newcontext); | 1663 | context_init(&newcontext); |
1607 | 1664 | ||
1608 | read_lock(&policy_rwlock); | 1665 | read_lock(&state->ss->policy_rwlock); |
1609 | 1666 | ||
1610 | if (kern) { | 1667 | if (kern) { |
1611 | tclass = unmap_class(orig_tclass); | 1668 | tclass = unmap_class(&state->ss->map, orig_tclass); |
1612 | sock = security_is_socket_class(orig_tclass); | 1669 | sock = security_is_socket_class(orig_tclass); |
1613 | } else { | 1670 | } else { |
1614 | tclass = orig_tclass; | 1671 | tclass = orig_tclass; |
1615 | sock = security_is_socket_class(map_class(tclass)); | 1672 | sock = security_is_socket_class(map_class(&state->ss->map, |
1673 | tclass)); | ||
1616 | } | 1674 | } |
1617 | 1675 | ||
1618 | scontext = sidtab_search(&sidtab, ssid); | 1676 | policydb = &state->ss->policydb; |
1677 | sidtab = &state->ss->sidtab; | ||
1678 | |||
1679 | scontext = sidtab_search(sidtab, ssid); | ||
1619 | if (!scontext) { | 1680 | if (!scontext) { |
1620 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1681 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1621 | __func__, ssid); | 1682 | __func__, ssid); |
1622 | rc = -EINVAL; | 1683 | rc = -EINVAL; |
1623 | goto out_unlock; | 1684 | goto out_unlock; |
1624 | } | 1685 | } |
1625 | tcontext = sidtab_search(&sidtab, tsid); | 1686 | tcontext = sidtab_search(sidtab, tsid); |
1626 | if (!tcontext) { | 1687 | if (!tcontext) { |
1627 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1688 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
1628 | __func__, tsid); | 1689 | __func__, tsid); |
@@ -1630,8 +1691,8 @@ static int security_compute_sid(u32 ssid, | |||
1630 | goto out_unlock; | 1691 | goto out_unlock; |
1631 | } | 1692 | } |
1632 | 1693 | ||
1633 | if (tclass && tclass <= policydb.p_classes.nprim) | 1694 | if (tclass && tclass <= policydb->p_classes.nprim) |
1634 | cladatum = policydb.class_val_to_struct[tclass - 1]; | 1695 | cladatum = policydb->class_val_to_struct[tclass - 1]; |
1635 | 1696 | ||
1636 | /* Set the user identity. */ | 1697 | /* Set the user identity. */ |
1637 | switch (specified) { | 1698 | switch (specified) { |
@@ -1657,7 +1718,7 @@ static int security_compute_sid(u32 ssid, | |||
1657 | } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { | 1718 | } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { |
1658 | newcontext.role = tcontext->role; | 1719 | newcontext.role = tcontext->role; |
1659 | } else { | 1720 | } else { |
1660 | if ((tclass == policydb.process_class) || (sock == true)) | 1721 | if ((tclass == policydb->process_class) || (sock == true)) |
1661 | newcontext.role = scontext->role; | 1722 | newcontext.role = scontext->role; |
1662 | else | 1723 | else |
1663 | newcontext.role = OBJECT_R_VAL; | 1724 | newcontext.role = OBJECT_R_VAL; |
@@ -1669,7 +1730,7 @@ static int security_compute_sid(u32 ssid, | |||
1669 | } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { | 1730 | } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { |
1670 | newcontext.type = tcontext->type; | 1731 | newcontext.type = tcontext->type; |
1671 | } else { | 1732 | } else { |
1672 | if ((tclass == policydb.process_class) || (sock == true)) { | 1733 | if ((tclass == policydb->process_class) || (sock == true)) { |
1673 | /* Use the type of process. */ | 1734 | /* Use the type of process. */ |
1674 | newcontext.type = scontext->type; | 1735 | newcontext.type = scontext->type; |
1675 | } else { | 1736 | } else { |
@@ -1683,11 +1744,11 @@ static int security_compute_sid(u32 ssid, | |||
1683 | avkey.target_type = tcontext->type; | 1744 | avkey.target_type = tcontext->type; |
1684 | avkey.target_class = tclass; | 1745 | avkey.target_class = tclass; |
1685 | avkey.specified = specified; | 1746 | avkey.specified = specified; |
1686 | avdatum = avtab_search(&policydb.te_avtab, &avkey); | 1747 | avdatum = avtab_search(&policydb->te_avtab, &avkey); |
1687 | 1748 | ||
1688 | /* If no permanent rule, also check for enabled conditional rules */ | 1749 | /* If no permanent rule, also check for enabled conditional rules */ |
1689 | if (!avdatum) { | 1750 | if (!avdatum) { |
1690 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); | 1751 | node = avtab_search_node(&policydb->te_cond_avtab, &avkey); |
1691 | for (; node; node = avtab_search_node_next(node, specified)) { | 1752 | for (; node; node = avtab_search_node_next(node, specified)) { |
1692 | if (node->key.specified & AVTAB_ENABLED) { | 1753 | if (node->key.specified & AVTAB_ENABLED) { |
1693 | avdatum = &node->datum; | 1754 | avdatum = &node->datum; |
@@ -1703,13 +1764,14 @@ static int security_compute_sid(u32 ssid, | |||
1703 | 1764 | ||
1704 | /* if we have a objname this is a file trans check so check those rules */ | 1765 | /* if we have a objname this is a file trans check so check those rules */ |
1705 | if (objname) | 1766 | if (objname) |
1706 | filename_compute_type(&policydb, &newcontext, scontext->type, | 1767 | filename_compute_type(policydb, &newcontext, scontext->type, |
1707 | tcontext->type, tclass, objname); | 1768 | tcontext->type, tclass, objname); |
1708 | 1769 | ||
1709 | /* Check for class-specific changes. */ | 1770 | /* Check for class-specific changes. */ |
1710 | if (specified & AVTAB_TRANSITION) { | 1771 | if (specified & AVTAB_TRANSITION) { |
1711 | /* Look for a role transition rule. */ | 1772 | /* Look for a role transition rule. */ |
1712 | for (roletr = policydb.role_tr; roletr; roletr = roletr->next) { | 1773 | for (roletr = policydb->role_tr; roletr; |
1774 | roletr = roletr->next) { | ||
1713 | if ((roletr->role == scontext->role) && | 1775 | if ((roletr->role == scontext->role) && |
1714 | (roletr->type == tcontext->type) && | 1776 | (roletr->type == tcontext->type) && |
1715 | (roletr->tclass == tclass)) { | 1777 | (roletr->tclass == tclass)) { |
@@ -1722,14 +1784,14 @@ static int security_compute_sid(u32 ssid, | |||
1722 | 1784 | ||
1723 | /* Set the MLS attributes. | 1785 | /* Set the MLS attributes. |
1724 | This is done last because it may allocate memory. */ | 1786 | This is done last because it may allocate memory. */ |
1725 | rc = mls_compute_sid(scontext, tcontext, tclass, specified, | 1787 | rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified, |
1726 | &newcontext, sock); | 1788 | &newcontext, sock); |
1727 | if (rc) | 1789 | if (rc) |
1728 | goto out_unlock; | 1790 | goto out_unlock; |
1729 | 1791 | ||
1730 | /* Check the validity of the context. */ | 1792 | /* Check the validity of the context. */ |
1731 | if (!policydb_context_isvalid(&policydb, &newcontext)) { | 1793 | if (!policydb_context_isvalid(policydb, &newcontext)) { |
1732 | rc = compute_sid_handle_invalid_context(scontext, | 1794 | rc = compute_sid_handle_invalid_context(state, scontext, |
1733 | tcontext, | 1795 | tcontext, |
1734 | tclass, | 1796 | tclass, |
1735 | &newcontext); | 1797 | &newcontext); |
@@ -1737,9 +1799,9 @@ static int security_compute_sid(u32 ssid, | |||
1737 | goto out_unlock; | 1799 | goto out_unlock; |
1738 | } | 1800 | } |
1739 | /* Obtain the sid for the context. */ | 1801 | /* Obtain the sid for the context. */ |
1740 | rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid); | 1802 | rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid); |
1741 | out_unlock: | 1803 | out_unlock: |
1742 | read_unlock(&policy_rwlock); | 1804 | read_unlock(&state->ss->policy_rwlock); |
1743 | context_destroy(&newcontext); | 1805 | context_destroy(&newcontext); |
1744 | out: | 1806 | out: |
1745 | return rc; | 1807 | return rc; |
@@ -1758,17 +1820,21 @@ out: | |||
1758 | * if insufficient memory is available, or %0 if the new SID was | 1820 | * if insufficient memory is available, or %0 if the new SID was |
1759 | * computed successfully. | 1821 | * computed successfully. |
1760 | */ | 1822 | */ |
1761 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | 1823 | int security_transition_sid(struct selinux_state *state, |
1824 | u32 ssid, u32 tsid, u16 tclass, | ||
1762 | const struct qstr *qstr, u32 *out_sid) | 1825 | const struct qstr *qstr, u32 *out_sid) |
1763 | { | 1826 | { |
1764 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1827 | return security_compute_sid(state, ssid, tsid, tclass, |
1828 | AVTAB_TRANSITION, | ||
1765 | qstr ? qstr->name : NULL, out_sid, true); | 1829 | qstr ? qstr->name : NULL, out_sid, true); |
1766 | } | 1830 | } |
1767 | 1831 | ||
1768 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, | 1832 | int security_transition_sid_user(struct selinux_state *state, |
1833 | u32 ssid, u32 tsid, u16 tclass, | ||
1769 | const char *objname, u32 *out_sid) | 1834 | const char *objname, u32 *out_sid) |
1770 | { | 1835 | { |
1771 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1836 | return security_compute_sid(state, ssid, tsid, tclass, |
1837 | AVTAB_TRANSITION, | ||
1772 | objname, out_sid, false); | 1838 | objname, out_sid, false); |
1773 | } | 1839 | } |
1774 | 1840 | ||
@@ -1785,12 +1851,14 @@ int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, | |||
1785 | * if insufficient memory is available, or %0 if the SID was | 1851 | * if insufficient memory is available, or %0 if the SID was |
1786 | * computed successfully. | 1852 | * computed successfully. |
1787 | */ | 1853 | */ |
1788 | int security_member_sid(u32 ssid, | 1854 | int security_member_sid(struct selinux_state *state, |
1855 | u32 ssid, | ||
1789 | u32 tsid, | 1856 | u32 tsid, |
1790 | u16 tclass, | 1857 | u16 tclass, |
1791 | u32 *out_sid) | 1858 | u32 *out_sid) |
1792 | { | 1859 | { |
1793 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL, | 1860 | return security_compute_sid(state, ssid, tsid, tclass, |
1861 | AVTAB_MEMBER, NULL, | ||
1794 | out_sid, false); | 1862 | out_sid, false); |
1795 | } | 1863 | } |
1796 | 1864 | ||
@@ -1807,12 +1875,14 @@ int security_member_sid(u32 ssid, | |||
1807 | * if insufficient memory is available, or %0 if the SID was | 1875 | * if insufficient memory is available, or %0 if the SID was |
1808 | * computed successfully. | 1876 | * computed successfully. |
1809 | */ | 1877 | */ |
1810 | int security_change_sid(u32 ssid, | 1878 | int security_change_sid(struct selinux_state *state, |
1879 | u32 ssid, | ||
1811 | u32 tsid, | 1880 | u32 tsid, |
1812 | u16 tclass, | 1881 | u16 tclass, |
1813 | u32 *out_sid) | 1882 | u32 *out_sid) |
1814 | { | 1883 | { |
1815 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, | 1884 | return security_compute_sid(state, |
1885 | ssid, tsid, tclass, AVTAB_CHANGE, NULL, | ||
1816 | out_sid, false); | 1886 | out_sid, false); |
1817 | } | 1887 | } |
1818 | 1888 | ||
@@ -1829,15 +1899,18 @@ static int clone_sid(u32 sid, | |||
1829 | return 0; | 1899 | return 0; |
1830 | } | 1900 | } |
1831 | 1901 | ||
1832 | static inline int convert_context_handle_invalid_context(struct context *context) | 1902 | static inline int convert_context_handle_invalid_context( |
1903 | struct selinux_state *state, | ||
1904 | struct context *context) | ||
1833 | { | 1905 | { |
1906 | struct policydb *policydb = &state->ss->policydb; | ||
1834 | char *s; | 1907 | char *s; |
1835 | u32 len; | 1908 | u32 len; |
1836 | 1909 | ||
1837 | if (selinux_enforcing) | 1910 | if (enforcing_enabled(state)) |
1838 | return -EINVAL; | 1911 | return -EINVAL; |
1839 | 1912 | ||
1840 | if (!context_struct_to_string(context, &s, &len)) { | 1913 | if (!context_struct_to_string(policydb, context, &s, &len)) { |
1841 | printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s); | 1914 | printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s); |
1842 | kfree(s); | 1915 | kfree(s); |
1843 | } | 1916 | } |
@@ -1845,6 +1918,7 @@ static inline int convert_context_handle_invalid_context(struct context *context | |||
1845 | } | 1918 | } |
1846 | 1919 | ||
1847 | struct convert_context_args { | 1920 | struct convert_context_args { |
1921 | struct selinux_state *state; | ||
1848 | struct policydb *oldp; | 1922 | struct policydb *oldp; |
1849 | struct policydb *newp; | 1923 | struct policydb *newp; |
1850 | }; | 1924 | }; |
@@ -1971,7 +2045,8 @@ static int convert_context(u32 key, | |||
1971 | 2045 | ||
1972 | /* Check the validity of the new context. */ | 2046 | /* Check the validity of the new context. */ |
1973 | if (!policydb_context_isvalid(args->newp, c)) { | 2047 | if (!policydb_context_isvalid(args->newp, c)) { |
1974 | rc = convert_context_handle_invalid_context(&oldc); | 2048 | rc = convert_context_handle_invalid_context(args->state, |
2049 | &oldc); | ||
1975 | if (rc) | 2050 | if (rc) |
1976 | goto bad; | 2051 | goto bad; |
1977 | } | 2052 | } |
@@ -1983,7 +2058,7 @@ out: | |||
1983 | return rc; | 2058 | return rc; |
1984 | bad: | 2059 | bad: |
1985 | /* Map old representation to string and save it. */ | 2060 | /* Map old representation to string and save it. */ |
1986 | rc = context_struct_to_string(&oldc, &s, &len); | 2061 | rc = context_struct_to_string(args->oldp, &oldc, &s, &len); |
1987 | if (rc) | 2062 | if (rc) |
1988 | return rc; | 2063 | return rc; |
1989 | context_destroy(&oldc); | 2064 | context_destroy(&oldc); |
@@ -1996,39 +2071,29 @@ bad: | |||
1996 | goto out; | 2071 | goto out; |
1997 | } | 2072 | } |
1998 | 2073 | ||
1999 | static void security_load_policycaps(void) | 2074 | static void security_load_policycaps(struct selinux_state *state) |
2000 | { | 2075 | { |
2076 | struct policydb *p = &state->ss->policydb; | ||
2001 | unsigned int i; | 2077 | unsigned int i; |
2002 | struct ebitmap_node *node; | 2078 | struct ebitmap_node *node; |
2003 | 2079 | ||
2004 | selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps, | 2080 | for (i = 0; i < ARRAY_SIZE(state->policycap); i++) |
2005 | POLICYDB_CAPABILITY_NETPEER); | 2081 | state->policycap[i] = ebitmap_get_bit(&p->policycaps, i); |
2006 | selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, | ||
2007 | POLICYDB_CAPABILITY_OPENPERM); | ||
2008 | selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps, | ||
2009 | POLICYDB_CAPABILITY_EXTSOCKCLASS); | ||
2010 | selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, | ||
2011 | POLICYDB_CAPABILITY_ALWAYSNETWORK); | ||
2012 | selinux_policycap_cgroupseclabel = | ||
2013 | ebitmap_get_bit(&policydb.policycaps, | ||
2014 | POLICYDB_CAPABILITY_CGROUPSECLABEL); | ||
2015 | selinux_policycap_nnp_nosuid_transition = | ||
2016 | ebitmap_get_bit(&policydb.policycaps, | ||
2017 | POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION); | ||
2018 | 2082 | ||
2019 | for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) | 2083 | for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) |
2020 | pr_info("SELinux: policy capability %s=%d\n", | 2084 | pr_info("SELinux: policy capability %s=%d\n", |
2021 | selinux_policycap_names[i], | 2085 | selinux_policycap_names[i], |
2022 | ebitmap_get_bit(&policydb.policycaps, i)); | 2086 | ebitmap_get_bit(&p->policycaps, i)); |
2023 | 2087 | ||
2024 | ebitmap_for_each_positive_bit(&policydb.policycaps, node, i) { | 2088 | ebitmap_for_each_positive_bit(&p->policycaps, node, i) { |
2025 | if (i >= ARRAY_SIZE(selinux_policycap_names)) | 2089 | if (i >= ARRAY_SIZE(selinux_policycap_names)) |
2026 | pr_info("SELinux: unknown policy capability %u\n", | 2090 | pr_info("SELinux: unknown policy capability %u\n", |
2027 | i); | 2091 | i); |
2028 | } | 2092 | } |
2029 | } | 2093 | } |
2030 | 2094 | ||
2031 | static int security_preserve_bools(struct policydb *p); | 2095 | static int security_preserve_bools(struct selinux_state *state, |
2096 | struct policydb *newpolicydb); | ||
2032 | 2097 | ||
2033 | /** | 2098 | /** |
2034 | * security_load_policy - Load a security policy configuration. | 2099 | * security_load_policy - Load a security policy configuration. |
@@ -2040,14 +2105,16 @@ static int security_preserve_bools(struct policydb *p); | |||
2040 | * This function will flush the access vector cache after | 2105 | * This function will flush the access vector cache after |
2041 | * loading the new policy. | 2106 | * loading the new policy. |
2042 | */ | 2107 | */ |
2043 | int security_load_policy(void *data, size_t len) | 2108 | int security_load_policy(struct selinux_state *state, void *data, size_t len) |
2044 | { | 2109 | { |
2110 | struct policydb *policydb; | ||
2111 | struct sidtab *sidtab; | ||
2045 | struct policydb *oldpolicydb, *newpolicydb; | 2112 | struct policydb *oldpolicydb, *newpolicydb; |
2046 | struct sidtab oldsidtab, newsidtab; | 2113 | struct sidtab oldsidtab, newsidtab; |
2047 | struct selinux_mapping *oldmap, *map = NULL; | 2114 | struct selinux_mapping *oldmapping; |
2115 | struct selinux_map newmap; | ||
2048 | struct convert_context_args args; | 2116 | struct convert_context_args args; |
2049 | u32 seqno; | 2117 | u32 seqno; |
2050 | u16 map_size; | ||
2051 | int rc = 0; | 2118 | int rc = 0; |
2052 | struct policy_file file = { data, len }, *fp = &file; | 2119 | struct policy_file file = { data, len }, *fp = &file; |
2053 | 2120 | ||
@@ -2058,53 +2125,42 @@ int security_load_policy(void *data, size_t len) | |||
2058 | } | 2125 | } |
2059 | newpolicydb = oldpolicydb + 1; | 2126 | newpolicydb = oldpolicydb + 1; |
2060 | 2127 | ||
2061 | if (!ss_initialized) { | 2128 | policydb = &state->ss->policydb; |
2062 | avtab_cache_init(); | 2129 | sidtab = &state->ss->sidtab; |
2063 | ebitmap_cache_init(); | 2130 | |
2064 | hashtab_cache_init(); | 2131 | if (!state->initialized) { |
2065 | rc = policydb_read(&policydb, fp); | 2132 | rc = policydb_read(policydb, fp); |
2066 | if (rc) { | 2133 | if (rc) |
2067 | avtab_cache_destroy(); | ||
2068 | ebitmap_cache_destroy(); | ||
2069 | hashtab_cache_destroy(); | ||
2070 | goto out; | 2134 | goto out; |
2071 | } | ||
2072 | 2135 | ||
2073 | policydb.len = len; | 2136 | policydb->len = len; |
2074 | rc = selinux_set_mapping(&policydb, secclass_map, | 2137 | rc = selinux_set_mapping(policydb, secclass_map, |
2075 | ¤t_mapping, | 2138 | &state->ss->map); |
2076 | ¤t_mapping_size); | ||
2077 | if (rc) { | 2139 | if (rc) { |
2078 | policydb_destroy(&policydb); | 2140 | policydb_destroy(policydb); |
2079 | avtab_cache_destroy(); | ||
2080 | ebitmap_cache_destroy(); | ||
2081 | hashtab_cache_destroy(); | ||
2082 | goto out; | 2141 | goto out; |
2083 | } | 2142 | } |
2084 | 2143 | ||
2085 | rc = policydb_load_isids(&policydb, &sidtab); | 2144 | rc = policydb_load_isids(policydb, sidtab); |
2086 | if (rc) { | 2145 | if (rc) { |
2087 | policydb_destroy(&policydb); | 2146 | policydb_destroy(policydb); |
2088 | avtab_cache_destroy(); | ||
2089 | ebitmap_cache_destroy(); | ||
2090 | hashtab_cache_destroy(); | ||
2091 | goto out; | 2147 | goto out; |
2092 | } | 2148 | } |
2093 | 2149 | ||
2094 | security_load_policycaps(); | 2150 | security_load_policycaps(state); |
2095 | ss_initialized = 1; | 2151 | state->initialized = 1; |
2096 | seqno = ++latest_granting; | 2152 | seqno = ++state->ss->latest_granting; |
2097 | selinux_complete_init(); | 2153 | selinux_complete_init(); |
2098 | avc_ss_reset(seqno); | 2154 | avc_ss_reset(state->avc, seqno); |
2099 | selnl_notify_policyload(seqno); | 2155 | selnl_notify_policyload(seqno); |
2100 | selinux_status_update_policyload(seqno); | 2156 | selinux_status_update_policyload(state, seqno); |
2101 | selinux_netlbl_cache_invalidate(); | 2157 | selinux_netlbl_cache_invalidate(); |
2102 | selinux_xfrm_notify_policyload(); | 2158 | selinux_xfrm_notify_policyload(); |
2103 | goto out; | 2159 | goto out; |
2104 | } | 2160 | } |
2105 | 2161 | ||
2106 | #if 0 | 2162 | #if 0 |
2107 | sidtab_hash_eval(&sidtab, "sids"); | 2163 | sidtab_hash_eval(sidtab, "sids"); |
2108 | #endif | 2164 | #endif |
2109 | 2165 | ||
2110 | rc = policydb_read(newpolicydb, fp); | 2166 | rc = policydb_read(newpolicydb, fp); |
@@ -2113,9 +2169,9 @@ int security_load_policy(void *data, size_t len) | |||
2113 | 2169 | ||
2114 | newpolicydb->len = len; | 2170 | newpolicydb->len = len; |
2115 | /* If switching between different policy types, log MLS status */ | 2171 | /* If switching between different policy types, log MLS status */ |
2116 | if (policydb.mls_enabled && !newpolicydb->mls_enabled) | 2172 | if (policydb->mls_enabled && !newpolicydb->mls_enabled) |
2117 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | 2173 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); |
2118 | else if (!policydb.mls_enabled && newpolicydb->mls_enabled) | 2174 | else if (!policydb->mls_enabled && newpolicydb->mls_enabled) |
2119 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | 2175 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); |
2120 | 2176 | ||
2121 | rc = policydb_load_isids(newpolicydb, &newsidtab); | 2177 | rc = policydb_load_isids(newpolicydb, &newsidtab); |
@@ -2125,20 +2181,20 @@ int security_load_policy(void *data, size_t len) | |||
2125 | goto out; | 2181 | goto out; |
2126 | } | 2182 | } |
2127 | 2183 | ||
2128 | rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size); | 2184 | rc = selinux_set_mapping(newpolicydb, secclass_map, &newmap); |
2129 | if (rc) | 2185 | if (rc) |
2130 | goto err; | 2186 | goto err; |
2131 | 2187 | ||
2132 | rc = security_preserve_bools(newpolicydb); | 2188 | rc = security_preserve_bools(state, newpolicydb); |
2133 | if (rc) { | 2189 | if (rc) { |
2134 | printk(KERN_ERR "SELinux: unable to preserve booleans\n"); | 2190 | printk(KERN_ERR "SELinux: unable to preserve booleans\n"); |
2135 | goto err; | 2191 | goto err; |
2136 | } | 2192 | } |
2137 | 2193 | ||
2138 | /* Clone the SID table. */ | 2194 | /* Clone the SID table. */ |
2139 | sidtab_shutdown(&sidtab); | 2195 | sidtab_shutdown(sidtab); |
2140 | 2196 | ||
2141 | rc = sidtab_map(&sidtab, clone_sid, &newsidtab); | 2197 | rc = sidtab_map(sidtab, clone_sid, &newsidtab); |
2142 | if (rc) | 2198 | if (rc) |
2143 | goto err; | 2199 | goto err; |
2144 | 2200 | ||
@@ -2146,7 +2202,8 @@ int security_load_policy(void *data, size_t len) | |||
2146 | * Convert the internal representations of contexts | 2202 | * Convert the internal representations of contexts |
2147 | * in the new SID table. | 2203 | * in the new SID table. |
2148 | */ | 2204 | */ |
2149 | args.oldp = &policydb; | 2205 | args.state = state; |
2206 | args.oldp = policydb; | ||
2150 | args.newp = newpolicydb; | 2207 | args.newp = newpolicydb; |
2151 | rc = sidtab_map(&newsidtab, convert_context, &args); | 2208 | rc = sidtab_map(&newsidtab, convert_context, &args); |
2152 | if (rc) { | 2209 | if (rc) { |
@@ -2157,28 +2214,28 @@ int security_load_policy(void *data, size_t len) | |||
2157 | } | 2214 | } |
2158 | 2215 | ||
2159 | /* Save the old policydb and SID table to free later. */ | 2216 | /* Save the old policydb and SID table to free later. */ |
2160 | memcpy(oldpolicydb, &policydb, sizeof(policydb)); | 2217 | memcpy(oldpolicydb, policydb, sizeof(*policydb)); |
2161 | sidtab_set(&oldsidtab, &sidtab); | 2218 | sidtab_set(&oldsidtab, sidtab); |
2162 | 2219 | ||
2163 | /* Install the new policydb and SID table. */ | 2220 | /* Install the new policydb and SID table. */ |
2164 | write_lock_irq(&policy_rwlock); | 2221 | write_lock_irq(&state->ss->policy_rwlock); |
2165 | memcpy(&policydb, newpolicydb, sizeof(policydb)); | 2222 | memcpy(policydb, newpolicydb, sizeof(*policydb)); |
2166 | sidtab_set(&sidtab, &newsidtab); | 2223 | sidtab_set(sidtab, &newsidtab); |
2167 | security_load_policycaps(); | 2224 | security_load_policycaps(state); |
2168 | oldmap = current_mapping; | 2225 | oldmapping = state->ss->map.mapping; |
2169 | current_mapping = map; | 2226 | state->ss->map.mapping = newmap.mapping; |
2170 | current_mapping_size = map_size; | 2227 | state->ss->map.size = newmap.size; |
2171 | seqno = ++latest_granting; | 2228 | seqno = ++state->ss->latest_granting; |
2172 | write_unlock_irq(&policy_rwlock); | 2229 | write_unlock_irq(&state->ss->policy_rwlock); |
2173 | 2230 | ||
2174 | /* Free the old policydb and SID table. */ | 2231 | /* Free the old policydb and SID table. */ |
2175 | policydb_destroy(oldpolicydb); | 2232 | policydb_destroy(oldpolicydb); |
2176 | sidtab_destroy(&oldsidtab); | 2233 | sidtab_destroy(&oldsidtab); |
2177 | kfree(oldmap); | 2234 | kfree(oldmapping); |
2178 | 2235 | ||
2179 | avc_ss_reset(seqno); | 2236 | avc_ss_reset(state->avc, seqno); |
2180 | selnl_notify_policyload(seqno); | 2237 | selnl_notify_policyload(seqno); |
2181 | selinux_status_update_policyload(seqno); | 2238 | selinux_status_update_policyload(state, seqno); |
2182 | selinux_netlbl_cache_invalidate(); | 2239 | selinux_netlbl_cache_invalidate(); |
2183 | selinux_xfrm_notify_policyload(); | 2240 | selinux_xfrm_notify_policyload(); |
2184 | 2241 | ||
@@ -2186,7 +2243,7 @@ int security_load_policy(void *data, size_t len) | |||
2186 | goto out; | 2243 | goto out; |
2187 | 2244 | ||
2188 | err: | 2245 | err: |
2189 | kfree(map); | 2246 | kfree(newmap.mapping); |
2190 | sidtab_destroy(&newsidtab); | 2247 | sidtab_destroy(&newsidtab); |
2191 | policydb_destroy(newpolicydb); | 2248 | policydb_destroy(newpolicydb); |
2192 | 2249 | ||
@@ -2195,13 +2252,14 @@ out: | |||
2195 | return rc; | 2252 | return rc; |
2196 | } | 2253 | } |
2197 | 2254 | ||
2198 | size_t security_policydb_len(void) | 2255 | size_t security_policydb_len(struct selinux_state *state) |
2199 | { | 2256 | { |
2257 | struct policydb *p = &state->ss->policydb; | ||
2200 | size_t len; | 2258 | size_t len; |
2201 | 2259 | ||
2202 | read_lock(&policy_rwlock); | 2260 | read_lock(&state->ss->policy_rwlock); |
2203 | len = policydb.len; | 2261 | len = p->len; |
2204 | read_unlock(&policy_rwlock); | 2262 | read_unlock(&state->ss->policy_rwlock); |
2205 | 2263 | ||
2206 | return len; | 2264 | return len; |
2207 | } | 2265 | } |
@@ -2212,14 +2270,20 @@ size_t security_policydb_len(void) | |||
2212 | * @port: port number | 2270 | * @port: port number |
2213 | * @out_sid: security identifier | 2271 | * @out_sid: security identifier |
2214 | */ | 2272 | */ |
2215 | int security_port_sid(u8 protocol, u16 port, u32 *out_sid) | 2273 | int security_port_sid(struct selinux_state *state, |
2274 | u8 protocol, u16 port, u32 *out_sid) | ||
2216 | { | 2275 | { |
2276 | struct policydb *policydb; | ||
2277 | struct sidtab *sidtab; | ||
2217 | struct ocontext *c; | 2278 | struct ocontext *c; |
2218 | int rc = 0; | 2279 | int rc = 0; |
2219 | 2280 | ||
2220 | read_lock(&policy_rwlock); | 2281 | read_lock(&state->ss->policy_rwlock); |
2221 | 2282 | ||
2222 | c = policydb.ocontexts[OCON_PORT]; | 2283 | policydb = &state->ss->policydb; |
2284 | sidtab = &state->ss->sidtab; | ||
2285 | |||
2286 | c = policydb->ocontexts[OCON_PORT]; | ||
2223 | while (c) { | 2287 | while (c) { |
2224 | if (c->u.port.protocol == protocol && | 2288 | if (c->u.port.protocol == protocol && |
2225 | c->u.port.low_port <= port && | 2289 | c->u.port.low_port <= port && |
@@ -2230,7 +2294,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid) | |||
2230 | 2294 | ||
2231 | if (c) { | 2295 | if (c) { |
2232 | if (!c->sid[0]) { | 2296 | if (!c->sid[0]) { |
2233 | rc = sidtab_context_to_sid(&sidtab, | 2297 | rc = sidtab_context_to_sid(sidtab, |
2234 | &c->context[0], | 2298 | &c->context[0], |
2235 | &c->sid[0]); | 2299 | &c->sid[0]); |
2236 | if (rc) | 2300 | if (rc) |
@@ -2242,7 +2306,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid) | |||
2242 | } | 2306 | } |
2243 | 2307 | ||
2244 | out: | 2308 | out: |
2245 | read_unlock(&policy_rwlock); | 2309 | read_unlock(&state->ss->policy_rwlock); |
2246 | return rc; | 2310 | return rc; |
2247 | } | 2311 | } |
2248 | 2312 | ||
@@ -2252,14 +2316,20 @@ out: | |||
2252 | * @pkey_num: pkey number | 2316 | * @pkey_num: pkey number |
2253 | * @out_sid: security identifier | 2317 | * @out_sid: security identifier |
2254 | */ | 2318 | */ |
2255 | int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) | 2319 | int security_ib_pkey_sid(struct selinux_state *state, |
2320 | u64 subnet_prefix, u16 pkey_num, u32 *out_sid) | ||
2256 | { | 2321 | { |
2322 | struct policydb *policydb; | ||
2323 | struct sidtab *sidtab; | ||
2257 | struct ocontext *c; | 2324 | struct ocontext *c; |
2258 | int rc = 0; | 2325 | int rc = 0; |
2259 | 2326 | ||
2260 | read_lock(&policy_rwlock); | 2327 | read_lock(&state->ss->policy_rwlock); |
2328 | |||
2329 | policydb = &state->ss->policydb; | ||
2330 | sidtab = &state->ss->sidtab; | ||
2261 | 2331 | ||
2262 | c = policydb.ocontexts[OCON_IBPKEY]; | 2332 | c = policydb->ocontexts[OCON_IBPKEY]; |
2263 | while (c) { | 2333 | while (c) { |
2264 | if (c->u.ibpkey.low_pkey <= pkey_num && | 2334 | if (c->u.ibpkey.low_pkey <= pkey_num && |
2265 | c->u.ibpkey.high_pkey >= pkey_num && | 2335 | c->u.ibpkey.high_pkey >= pkey_num && |
@@ -2271,7 +2341,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) | |||
2271 | 2341 | ||
2272 | if (c) { | 2342 | if (c) { |
2273 | if (!c->sid[0]) { | 2343 | if (!c->sid[0]) { |
2274 | rc = sidtab_context_to_sid(&sidtab, | 2344 | rc = sidtab_context_to_sid(sidtab, |
2275 | &c->context[0], | 2345 | &c->context[0], |
2276 | &c->sid[0]); | 2346 | &c->sid[0]); |
2277 | if (rc) | 2347 | if (rc) |
@@ -2282,7 +2352,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) | |||
2282 | *out_sid = SECINITSID_UNLABELED; | 2352 | *out_sid = SECINITSID_UNLABELED; |
2283 | 2353 | ||
2284 | out: | 2354 | out: |
2285 | read_unlock(&policy_rwlock); | 2355 | read_unlock(&state->ss->policy_rwlock); |
2286 | return rc; | 2356 | return rc; |
2287 | } | 2357 | } |
2288 | 2358 | ||
@@ -2292,14 +2362,20 @@ out: | |||
2292 | * @port: port number | 2362 | * @port: port number |
2293 | * @out_sid: security identifier | 2363 | * @out_sid: security identifier |
2294 | */ | 2364 | */ |
2295 | int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) | 2365 | int security_ib_endport_sid(struct selinux_state *state, |
2366 | const char *dev_name, u8 port_num, u32 *out_sid) | ||
2296 | { | 2367 | { |
2368 | struct policydb *policydb; | ||
2369 | struct sidtab *sidtab; | ||
2297 | struct ocontext *c; | 2370 | struct ocontext *c; |
2298 | int rc = 0; | 2371 | int rc = 0; |
2299 | 2372 | ||
2300 | read_lock(&policy_rwlock); | 2373 | read_lock(&state->ss->policy_rwlock); |
2374 | |||
2375 | policydb = &state->ss->policydb; | ||
2376 | sidtab = &state->ss->sidtab; | ||
2301 | 2377 | ||
2302 | c = policydb.ocontexts[OCON_IBENDPORT]; | 2378 | c = policydb->ocontexts[OCON_IBENDPORT]; |
2303 | while (c) { | 2379 | while (c) { |
2304 | if (c->u.ibendport.port == port_num && | 2380 | if (c->u.ibendport.port == port_num && |
2305 | !strncmp(c->u.ibendport.dev_name, | 2381 | !strncmp(c->u.ibendport.dev_name, |
@@ -2312,7 +2388,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) | |||
2312 | 2388 | ||
2313 | if (c) { | 2389 | if (c) { |
2314 | if (!c->sid[0]) { | 2390 | if (!c->sid[0]) { |
2315 | rc = sidtab_context_to_sid(&sidtab, | 2391 | rc = sidtab_context_to_sid(sidtab, |
2316 | &c->context[0], | 2392 | &c->context[0], |
2317 | &c->sid[0]); | 2393 | &c->sid[0]); |
2318 | if (rc) | 2394 | if (rc) |
@@ -2323,7 +2399,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) | |||
2323 | *out_sid = SECINITSID_UNLABELED; | 2399 | *out_sid = SECINITSID_UNLABELED; |
2324 | 2400 | ||
2325 | out: | 2401 | out: |
2326 | read_unlock(&policy_rwlock); | 2402 | read_unlock(&state->ss->policy_rwlock); |
2327 | return rc; | 2403 | return rc; |
2328 | } | 2404 | } |
2329 | 2405 | ||
@@ -2332,14 +2408,20 @@ out: | |||
2332 | * @name: interface name | 2408 | * @name: interface name |
2333 | * @if_sid: interface SID | 2409 | * @if_sid: interface SID |
2334 | */ | 2410 | */ |
2335 | int security_netif_sid(char *name, u32 *if_sid) | 2411 | int security_netif_sid(struct selinux_state *state, |
2412 | char *name, u32 *if_sid) | ||
2336 | { | 2413 | { |
2414 | struct policydb *policydb; | ||
2415 | struct sidtab *sidtab; | ||
2337 | int rc = 0; | 2416 | int rc = 0; |
2338 | struct ocontext *c; | 2417 | struct ocontext *c; |
2339 | 2418 | ||
2340 | read_lock(&policy_rwlock); | 2419 | read_lock(&state->ss->policy_rwlock); |
2341 | 2420 | ||
2342 | c = policydb.ocontexts[OCON_NETIF]; | 2421 | policydb = &state->ss->policydb; |
2422 | sidtab = &state->ss->sidtab; | ||
2423 | |||
2424 | c = policydb->ocontexts[OCON_NETIF]; | ||
2343 | while (c) { | 2425 | while (c) { |
2344 | if (strcmp(name, c->u.name) == 0) | 2426 | if (strcmp(name, c->u.name) == 0) |
2345 | break; | 2427 | break; |
@@ -2348,12 +2430,12 @@ int security_netif_sid(char *name, u32 *if_sid) | |||
2348 | 2430 | ||
2349 | if (c) { | 2431 | if (c) { |
2350 | if (!c->sid[0] || !c->sid[1]) { | 2432 | if (!c->sid[0] || !c->sid[1]) { |
2351 | rc = sidtab_context_to_sid(&sidtab, | 2433 | rc = sidtab_context_to_sid(sidtab, |
2352 | &c->context[0], | 2434 | &c->context[0], |
2353 | &c->sid[0]); | 2435 | &c->sid[0]); |
2354 | if (rc) | 2436 | if (rc) |
2355 | goto out; | 2437 | goto out; |
2356 | rc = sidtab_context_to_sid(&sidtab, | 2438 | rc = sidtab_context_to_sid(sidtab, |
2357 | &c->context[1], | 2439 | &c->context[1], |
2358 | &c->sid[1]); | 2440 | &c->sid[1]); |
2359 | if (rc) | 2441 | if (rc) |
@@ -2364,7 +2446,7 @@ int security_netif_sid(char *name, u32 *if_sid) | |||
2364 | *if_sid = SECINITSID_NETIF; | 2446 | *if_sid = SECINITSID_NETIF; |
2365 | 2447 | ||
2366 | out: | 2448 | out: |
2367 | read_unlock(&policy_rwlock); | 2449 | read_unlock(&state->ss->policy_rwlock); |
2368 | return rc; | 2450 | return rc; |
2369 | } | 2451 | } |
2370 | 2452 | ||
@@ -2388,15 +2470,21 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask) | |||
2388 | * @addrlen: address length in bytes | 2470 | * @addrlen: address length in bytes |
2389 | * @out_sid: security identifier | 2471 | * @out_sid: security identifier |
2390 | */ | 2472 | */ |
2391 | int security_node_sid(u16 domain, | 2473 | int security_node_sid(struct selinux_state *state, |
2474 | u16 domain, | ||
2392 | void *addrp, | 2475 | void *addrp, |
2393 | u32 addrlen, | 2476 | u32 addrlen, |
2394 | u32 *out_sid) | 2477 | u32 *out_sid) |
2395 | { | 2478 | { |
2479 | struct policydb *policydb; | ||
2480 | struct sidtab *sidtab; | ||
2396 | int rc; | 2481 | int rc; |
2397 | struct ocontext *c; | 2482 | struct ocontext *c; |
2398 | 2483 | ||
2399 | read_lock(&policy_rwlock); | 2484 | read_lock(&state->ss->policy_rwlock); |
2485 | |||
2486 | policydb = &state->ss->policydb; | ||
2487 | sidtab = &state->ss->sidtab; | ||
2400 | 2488 | ||
2401 | switch (domain) { | 2489 | switch (domain) { |
2402 | case AF_INET: { | 2490 | case AF_INET: { |
@@ -2408,7 +2496,7 @@ int security_node_sid(u16 domain, | |||
2408 | 2496 | ||
2409 | addr = *((u32 *)addrp); | 2497 | addr = *((u32 *)addrp); |
2410 | 2498 | ||
2411 | c = policydb.ocontexts[OCON_NODE]; | 2499 | c = policydb->ocontexts[OCON_NODE]; |
2412 | while (c) { | 2500 | while (c) { |
2413 | if (c->u.node.addr == (addr & c->u.node.mask)) | 2501 | if (c->u.node.addr == (addr & c->u.node.mask)) |
2414 | break; | 2502 | break; |
@@ -2421,7 +2509,7 @@ int security_node_sid(u16 domain, | |||
2421 | rc = -EINVAL; | 2509 | rc = -EINVAL; |
2422 | if (addrlen != sizeof(u64) * 2) | 2510 | if (addrlen != sizeof(u64) * 2) |
2423 | goto out; | 2511 | goto out; |
2424 | c = policydb.ocontexts[OCON_NODE6]; | 2512 | c = policydb->ocontexts[OCON_NODE6]; |
2425 | while (c) { | 2513 | while (c) { |
2426 | if (match_ipv6_addrmask(addrp, c->u.node6.addr, | 2514 | if (match_ipv6_addrmask(addrp, c->u.node6.addr, |
2427 | c->u.node6.mask)) | 2515 | c->u.node6.mask)) |
@@ -2438,7 +2526,7 @@ int security_node_sid(u16 domain, | |||
2438 | 2526 | ||
2439 | if (c) { | 2527 | if (c) { |
2440 | if (!c->sid[0]) { | 2528 | if (!c->sid[0]) { |
2441 | rc = sidtab_context_to_sid(&sidtab, | 2529 | rc = sidtab_context_to_sid(sidtab, |
2442 | &c->context[0], | 2530 | &c->context[0], |
2443 | &c->sid[0]); | 2531 | &c->sid[0]); |
2444 | if (rc) | 2532 | if (rc) |
@@ -2451,7 +2539,7 @@ int security_node_sid(u16 domain, | |||
2451 | 2539 | ||
2452 | rc = 0; | 2540 | rc = 0; |
2453 | out: | 2541 | out: |
2454 | read_unlock(&policy_rwlock); | 2542 | read_unlock(&state->ss->policy_rwlock); |
2455 | return rc; | 2543 | return rc; |
2456 | } | 2544 | } |
2457 | 2545 | ||
@@ -2471,11 +2559,14 @@ out: | |||
2471 | * number of elements in the array. | 2559 | * number of elements in the array. |
2472 | */ | 2560 | */ |
2473 | 2561 | ||
2474 | int security_get_user_sids(u32 fromsid, | 2562 | int security_get_user_sids(struct selinux_state *state, |
2563 | u32 fromsid, | ||
2475 | char *username, | 2564 | char *username, |
2476 | u32 **sids, | 2565 | u32 **sids, |
2477 | u32 *nel) | 2566 | u32 *nel) |
2478 | { | 2567 | { |
2568 | struct policydb *policydb; | ||
2569 | struct sidtab *sidtab; | ||
2479 | struct context *fromcon, usercon; | 2570 | struct context *fromcon, usercon; |
2480 | u32 *mysids = NULL, *mysids2, sid; | 2571 | u32 *mysids = NULL, *mysids2, sid; |
2481 | u32 mynel = 0, maxnel = SIDS_NEL; | 2572 | u32 mynel = 0, maxnel = SIDS_NEL; |
@@ -2487,20 +2578,23 @@ int security_get_user_sids(u32 fromsid, | |||
2487 | *sids = NULL; | 2578 | *sids = NULL; |
2488 | *nel = 0; | 2579 | *nel = 0; |
2489 | 2580 | ||
2490 | if (!ss_initialized) | 2581 | if (!state->initialized) |
2491 | goto out; | 2582 | goto out; |
2492 | 2583 | ||
2493 | read_lock(&policy_rwlock); | 2584 | read_lock(&state->ss->policy_rwlock); |
2585 | |||
2586 | policydb = &state->ss->policydb; | ||
2587 | sidtab = &state->ss->sidtab; | ||
2494 | 2588 | ||
2495 | context_init(&usercon); | 2589 | context_init(&usercon); |
2496 | 2590 | ||
2497 | rc = -EINVAL; | 2591 | rc = -EINVAL; |
2498 | fromcon = sidtab_search(&sidtab, fromsid); | 2592 | fromcon = sidtab_search(sidtab, fromsid); |
2499 | if (!fromcon) | 2593 | if (!fromcon) |
2500 | goto out_unlock; | 2594 | goto out_unlock; |
2501 | 2595 | ||
2502 | rc = -EINVAL; | 2596 | rc = -EINVAL; |
2503 | user = hashtab_search(policydb.p_users.table, username); | 2597 | user = hashtab_search(policydb->p_users.table, username); |
2504 | if (!user) | 2598 | if (!user) |
2505 | goto out_unlock; | 2599 | goto out_unlock; |
2506 | 2600 | ||
@@ -2512,15 +2606,16 @@ int security_get_user_sids(u32 fromsid, | |||
2512 | goto out_unlock; | 2606 | goto out_unlock; |
2513 | 2607 | ||
2514 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { | 2608 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
2515 | role = policydb.role_val_to_struct[i]; | 2609 | role = policydb->role_val_to_struct[i]; |
2516 | usercon.role = i + 1; | 2610 | usercon.role = i + 1; |
2517 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { | 2611 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
2518 | usercon.type = j + 1; | 2612 | usercon.type = j + 1; |
2519 | 2613 | ||
2520 | if (mls_setup_user_range(fromcon, user, &usercon)) | 2614 | if (mls_setup_user_range(policydb, fromcon, user, |
2615 | &usercon)) | ||
2521 | continue; | 2616 | continue; |
2522 | 2617 | ||
2523 | rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); | 2618 | rc = sidtab_context_to_sid(sidtab, &usercon, &sid); |
2524 | if (rc) | 2619 | if (rc) |
2525 | goto out_unlock; | 2620 | goto out_unlock; |
2526 | if (mynel < maxnel) { | 2621 | if (mynel < maxnel) { |
@@ -2540,7 +2635,7 @@ int security_get_user_sids(u32 fromsid, | |||
2540 | } | 2635 | } |
2541 | rc = 0; | 2636 | rc = 0; |
2542 | out_unlock: | 2637 | out_unlock: |
2543 | read_unlock(&policy_rwlock); | 2638 | read_unlock(&state->ss->policy_rwlock); |
2544 | if (rc || !mynel) { | 2639 | if (rc || !mynel) { |
2545 | kfree(mysids); | 2640 | kfree(mysids); |
2546 | goto out; | 2641 | goto out; |
@@ -2554,7 +2649,8 @@ out_unlock: | |||
2554 | } | 2649 | } |
2555 | for (i = 0, j = 0; i < mynel; i++) { | 2650 | for (i = 0, j = 0; i < mynel; i++) { |
2556 | struct av_decision dummy_avd; | 2651 | struct av_decision dummy_avd; |
2557 | rc = avc_has_perm_noaudit(fromsid, mysids[i], | 2652 | rc = avc_has_perm_noaudit(state, |
2653 | fromsid, mysids[i], | ||
2558 | SECCLASS_PROCESS, /* kernel value */ | 2654 | SECCLASS_PROCESS, /* kernel value */ |
2559 | PROCESS__TRANSITION, AVC_STRICT, | 2655 | PROCESS__TRANSITION, AVC_STRICT, |
2560 | &dummy_avd); | 2656 | &dummy_avd); |
@@ -2583,11 +2679,14 @@ out: | |||
2583 | * | 2679 | * |
2584 | * The caller must acquire the policy_rwlock before calling this function. | 2680 | * The caller must acquire the policy_rwlock before calling this function. |
2585 | */ | 2681 | */ |
2586 | static inline int __security_genfs_sid(const char *fstype, | 2682 | static inline int __security_genfs_sid(struct selinux_state *state, |
2683 | const char *fstype, | ||
2587 | char *path, | 2684 | char *path, |
2588 | u16 orig_sclass, | 2685 | u16 orig_sclass, |
2589 | u32 *sid) | 2686 | u32 *sid) |
2590 | { | 2687 | { |
2688 | struct policydb *policydb = &state->ss->policydb; | ||
2689 | struct sidtab *sidtab = &state->ss->sidtab; | ||
2591 | int len; | 2690 | int len; |
2592 | u16 sclass; | 2691 | u16 sclass; |
2593 | struct genfs *genfs; | 2692 | struct genfs *genfs; |
@@ -2597,10 +2696,10 @@ static inline int __security_genfs_sid(const char *fstype, | |||
2597 | while (path[0] == '/' && path[1] == '/') | 2696 | while (path[0] == '/' && path[1] == '/') |
2598 | path++; | 2697 | path++; |
2599 | 2698 | ||
2600 | sclass = unmap_class(orig_sclass); | 2699 | sclass = unmap_class(&state->ss->map, orig_sclass); |
2601 | *sid = SECINITSID_UNLABELED; | 2700 | *sid = SECINITSID_UNLABELED; |
2602 | 2701 | ||
2603 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { | 2702 | for (genfs = policydb->genfs; genfs; genfs = genfs->next) { |
2604 | cmp = strcmp(fstype, genfs->fstype); | 2703 | cmp = strcmp(fstype, genfs->fstype); |
2605 | if (cmp <= 0) | 2704 | if (cmp <= 0) |
2606 | break; | 2705 | break; |
@@ -2622,7 +2721,7 @@ static inline int __security_genfs_sid(const char *fstype, | |||
2622 | goto out; | 2721 | goto out; |
2623 | 2722 | ||
2624 | if (!c->sid[0]) { | 2723 | if (!c->sid[0]) { |
2625 | rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); | 2724 | rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); |
2626 | if (rc) | 2725 | if (rc) |
2627 | goto out; | 2726 | goto out; |
2628 | } | 2727 | } |
@@ -2643,16 +2742,17 @@ out: | |||
2643 | * Acquire policy_rwlock before calling __security_genfs_sid() and release | 2742 | * Acquire policy_rwlock before calling __security_genfs_sid() and release |
2644 | * it afterward. | 2743 | * it afterward. |
2645 | */ | 2744 | */ |
2646 | int security_genfs_sid(const char *fstype, | 2745 | int security_genfs_sid(struct selinux_state *state, |
2746 | const char *fstype, | ||
2647 | char *path, | 2747 | char *path, |
2648 | u16 orig_sclass, | 2748 | u16 orig_sclass, |
2649 | u32 *sid) | 2749 | u32 *sid) |
2650 | { | 2750 | { |
2651 | int retval; | 2751 | int retval; |
2652 | 2752 | ||
2653 | read_lock(&policy_rwlock); | 2753 | read_lock(&state->ss->policy_rwlock); |
2654 | retval = __security_genfs_sid(fstype, path, orig_sclass, sid); | 2754 | retval = __security_genfs_sid(state, fstype, path, orig_sclass, sid); |
2655 | read_unlock(&policy_rwlock); | 2755 | read_unlock(&state->ss->policy_rwlock); |
2656 | return retval; | 2756 | return retval; |
2657 | } | 2757 | } |
2658 | 2758 | ||
@@ -2660,16 +2760,21 @@ int security_genfs_sid(const char *fstype, | |||
2660 | * security_fs_use - Determine how to handle labeling for a filesystem. | 2760 | * security_fs_use - Determine how to handle labeling for a filesystem. |
2661 | * @sb: superblock in question | 2761 | * @sb: superblock in question |
2662 | */ | 2762 | */ |
2663 | int security_fs_use(struct super_block *sb) | 2763 | int security_fs_use(struct selinux_state *state, struct super_block *sb) |
2664 | { | 2764 | { |
2765 | struct policydb *policydb; | ||
2766 | struct sidtab *sidtab; | ||
2665 | int rc = 0; | 2767 | int rc = 0; |
2666 | struct ocontext *c; | 2768 | struct ocontext *c; |
2667 | struct superblock_security_struct *sbsec = sb->s_security; | 2769 | struct superblock_security_struct *sbsec = sb->s_security; |
2668 | const char *fstype = sb->s_type->name; | 2770 | const char *fstype = sb->s_type->name; |
2669 | 2771 | ||
2670 | read_lock(&policy_rwlock); | 2772 | read_lock(&state->ss->policy_rwlock); |
2671 | 2773 | ||
2672 | c = policydb.ocontexts[OCON_FSUSE]; | 2774 | policydb = &state->ss->policydb; |
2775 | sidtab = &state->ss->sidtab; | ||
2776 | |||
2777 | c = policydb->ocontexts[OCON_FSUSE]; | ||
2673 | while (c) { | 2778 | while (c) { |
2674 | if (strcmp(fstype, c->u.name) == 0) | 2779 | if (strcmp(fstype, c->u.name) == 0) |
2675 | break; | 2780 | break; |
@@ -2679,14 +2784,14 @@ int security_fs_use(struct super_block *sb) | |||
2679 | if (c) { | 2784 | if (c) { |
2680 | sbsec->behavior = c->v.behavior; | 2785 | sbsec->behavior = c->v.behavior; |
2681 | if (!c->sid[0]) { | 2786 | if (!c->sid[0]) { |
2682 | rc = sidtab_context_to_sid(&sidtab, &c->context[0], | 2787 | rc = sidtab_context_to_sid(sidtab, &c->context[0], |
2683 | &c->sid[0]); | 2788 | &c->sid[0]); |
2684 | if (rc) | 2789 | if (rc) |
2685 | goto out; | 2790 | goto out; |
2686 | } | 2791 | } |
2687 | sbsec->sid = c->sid[0]; | 2792 | sbsec->sid = c->sid[0]; |
2688 | } else { | 2793 | } else { |
2689 | rc = __security_genfs_sid(fstype, "/", SECCLASS_DIR, | 2794 | rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR, |
2690 | &sbsec->sid); | 2795 | &sbsec->sid); |
2691 | if (rc) { | 2796 | if (rc) { |
2692 | sbsec->behavior = SECURITY_FS_USE_NONE; | 2797 | sbsec->behavior = SECURITY_FS_USE_NONE; |
@@ -2697,20 +2802,32 @@ int security_fs_use(struct super_block *sb) | |||
2697 | } | 2802 | } |
2698 | 2803 | ||
2699 | out: | 2804 | out: |
2700 | read_unlock(&policy_rwlock); | 2805 | read_unlock(&state->ss->policy_rwlock); |
2701 | return rc; | 2806 | return rc; |
2702 | } | 2807 | } |
2703 | 2808 | ||
2704 | int security_get_bools(int *len, char ***names, int **values) | 2809 | int security_get_bools(struct selinux_state *state, |
2810 | int *len, char ***names, int **values) | ||
2705 | { | 2811 | { |
2812 | struct policydb *policydb; | ||
2706 | int i, rc; | 2813 | int i, rc; |
2707 | 2814 | ||
2708 | read_lock(&policy_rwlock); | 2815 | if (!state->initialized) { |
2816 | *len = 0; | ||
2817 | *names = NULL; | ||
2818 | *values = NULL; | ||
2819 | return 0; | ||
2820 | } | ||
2821 | |||
2822 | read_lock(&state->ss->policy_rwlock); | ||
2823 | |||
2824 | policydb = &state->ss->policydb; | ||
2825 | |||
2709 | *names = NULL; | 2826 | *names = NULL; |
2710 | *values = NULL; | 2827 | *values = NULL; |
2711 | 2828 | ||
2712 | rc = 0; | 2829 | rc = 0; |
2713 | *len = policydb.p_bools.nprim; | 2830 | *len = policydb->p_bools.nprim; |
2714 | if (!*len) | 2831 | if (!*len) |
2715 | goto out; | 2832 | goto out; |
2716 | 2833 | ||
@@ -2725,16 +2842,17 @@ int security_get_bools(int *len, char ***names, int **values) | |||
2725 | goto err; | 2842 | goto err; |
2726 | 2843 | ||
2727 | for (i = 0; i < *len; i++) { | 2844 | for (i = 0; i < *len; i++) { |
2728 | (*values)[i] = policydb.bool_val_to_struct[i]->state; | 2845 | (*values)[i] = policydb->bool_val_to_struct[i]->state; |
2729 | 2846 | ||
2730 | rc = -ENOMEM; | 2847 | rc = -ENOMEM; |
2731 | (*names)[i] = kstrdup(sym_name(&policydb, SYM_BOOLS, i), GFP_ATOMIC); | 2848 | (*names)[i] = kstrdup(sym_name(policydb, SYM_BOOLS, i), |
2849 | GFP_ATOMIC); | ||
2732 | if (!(*names)[i]) | 2850 | if (!(*names)[i]) |
2733 | goto err; | 2851 | goto err; |
2734 | } | 2852 | } |
2735 | rc = 0; | 2853 | rc = 0; |
2736 | out: | 2854 | out: |
2737 | read_unlock(&policy_rwlock); | 2855 | read_unlock(&state->ss->policy_rwlock); |
2738 | return rc; | 2856 | return rc; |
2739 | err: | 2857 | err: |
2740 | if (*names) { | 2858 | if (*names) { |
@@ -2746,90 +2864,98 @@ err: | |||
2746 | } | 2864 | } |
2747 | 2865 | ||
2748 | 2866 | ||
2749 | int security_set_bools(int len, int *values) | 2867 | int security_set_bools(struct selinux_state *state, int len, int *values) |
2750 | { | 2868 | { |
2869 | struct policydb *policydb; | ||
2751 | int i, rc; | 2870 | int i, rc; |
2752 | int lenp, seqno = 0; | 2871 | int lenp, seqno = 0; |
2753 | struct cond_node *cur; | 2872 | struct cond_node *cur; |
2754 | 2873 | ||
2755 | write_lock_irq(&policy_rwlock); | 2874 | write_lock_irq(&state->ss->policy_rwlock); |
2875 | |||
2876 | policydb = &state->ss->policydb; | ||
2756 | 2877 | ||
2757 | rc = -EFAULT; | 2878 | rc = -EFAULT; |
2758 | lenp = policydb.p_bools.nprim; | 2879 | lenp = policydb->p_bools.nprim; |
2759 | if (len != lenp) | 2880 | if (len != lenp) |
2760 | goto out; | 2881 | goto out; |
2761 | 2882 | ||
2762 | for (i = 0; i < len; i++) { | 2883 | for (i = 0; i < len; i++) { |
2763 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { | 2884 | if (!!values[i] != policydb->bool_val_to_struct[i]->state) { |
2764 | audit_log(current->audit_context, GFP_ATOMIC, | 2885 | audit_log(current->audit_context, GFP_ATOMIC, |
2765 | AUDIT_MAC_CONFIG_CHANGE, | 2886 | AUDIT_MAC_CONFIG_CHANGE, |
2766 | "bool=%s val=%d old_val=%d auid=%u ses=%u", | 2887 | "bool=%s val=%d old_val=%d auid=%u ses=%u", |
2767 | sym_name(&policydb, SYM_BOOLS, i), | 2888 | sym_name(policydb, SYM_BOOLS, i), |
2768 | !!values[i], | 2889 | !!values[i], |
2769 | policydb.bool_val_to_struct[i]->state, | 2890 | policydb->bool_val_to_struct[i]->state, |
2770 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 2891 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
2771 | audit_get_sessionid(current)); | 2892 | audit_get_sessionid(current)); |
2772 | } | 2893 | } |
2773 | if (values[i]) | 2894 | if (values[i]) |
2774 | policydb.bool_val_to_struct[i]->state = 1; | 2895 | policydb->bool_val_to_struct[i]->state = 1; |
2775 | else | 2896 | else |
2776 | policydb.bool_val_to_struct[i]->state = 0; | 2897 | policydb->bool_val_to_struct[i]->state = 0; |
2777 | } | 2898 | } |
2778 | 2899 | ||
2779 | for (cur = policydb.cond_list; cur; cur = cur->next) { | 2900 | for (cur = policydb->cond_list; cur; cur = cur->next) { |
2780 | rc = evaluate_cond_node(&policydb, cur); | 2901 | rc = evaluate_cond_node(policydb, cur); |
2781 | if (rc) | 2902 | if (rc) |
2782 | goto out; | 2903 | goto out; |
2783 | } | 2904 | } |
2784 | 2905 | ||
2785 | seqno = ++latest_granting; | 2906 | seqno = ++state->ss->latest_granting; |
2786 | rc = 0; | 2907 | rc = 0; |
2787 | out: | 2908 | out: |
2788 | write_unlock_irq(&policy_rwlock); | 2909 | write_unlock_irq(&state->ss->policy_rwlock); |
2789 | if (!rc) { | 2910 | if (!rc) { |
2790 | avc_ss_reset(seqno); | 2911 | avc_ss_reset(state->avc, seqno); |
2791 | selnl_notify_policyload(seqno); | 2912 | selnl_notify_policyload(seqno); |
2792 | selinux_status_update_policyload(seqno); | 2913 | selinux_status_update_policyload(state, seqno); |
2793 | selinux_xfrm_notify_policyload(); | 2914 | selinux_xfrm_notify_policyload(); |
2794 | } | 2915 | } |
2795 | return rc; | 2916 | return rc; |
2796 | } | 2917 | } |
2797 | 2918 | ||
2798 | int security_get_bool_value(int index) | 2919 | int security_get_bool_value(struct selinux_state *state, |
2920 | int index) | ||
2799 | { | 2921 | { |
2922 | struct policydb *policydb; | ||
2800 | int rc; | 2923 | int rc; |
2801 | int len; | 2924 | int len; |
2802 | 2925 | ||
2803 | read_lock(&policy_rwlock); | 2926 | read_lock(&state->ss->policy_rwlock); |
2927 | |||
2928 | policydb = &state->ss->policydb; | ||
2804 | 2929 | ||
2805 | rc = -EFAULT; | 2930 | rc = -EFAULT; |
2806 | len = policydb.p_bools.nprim; | 2931 | len = policydb->p_bools.nprim; |
2807 | if (index >= len) | 2932 | if (index >= len) |
2808 | goto out; | 2933 | goto out; |
2809 | 2934 | ||
2810 | rc = policydb.bool_val_to_struct[index]->state; | 2935 | rc = policydb->bool_val_to_struct[index]->state; |
2811 | out: | 2936 | out: |
2812 | read_unlock(&policy_rwlock); | 2937 | read_unlock(&state->ss->policy_rwlock); |
2813 | return rc; | 2938 | return rc; |
2814 | } | 2939 | } |
2815 | 2940 | ||
2816 | static int security_preserve_bools(struct policydb *p) | 2941 | static int security_preserve_bools(struct selinux_state *state, |
2942 | struct policydb *policydb) | ||
2817 | { | 2943 | { |
2818 | int rc, nbools = 0, *bvalues = NULL, i; | 2944 | int rc, nbools = 0, *bvalues = NULL, i; |
2819 | char **bnames = NULL; | 2945 | char **bnames = NULL; |
2820 | struct cond_bool_datum *booldatum; | 2946 | struct cond_bool_datum *booldatum; |
2821 | struct cond_node *cur; | 2947 | struct cond_node *cur; |
2822 | 2948 | ||
2823 | rc = security_get_bools(&nbools, &bnames, &bvalues); | 2949 | rc = security_get_bools(state, &nbools, &bnames, &bvalues); |
2824 | if (rc) | 2950 | if (rc) |
2825 | goto out; | 2951 | goto out; |
2826 | for (i = 0; i < nbools; i++) { | 2952 | for (i = 0; i < nbools; i++) { |
2827 | booldatum = hashtab_search(p->p_bools.table, bnames[i]); | 2953 | booldatum = hashtab_search(policydb->p_bools.table, bnames[i]); |
2828 | if (booldatum) | 2954 | if (booldatum) |
2829 | booldatum->state = bvalues[i]; | 2955 | booldatum->state = bvalues[i]; |
2830 | } | 2956 | } |
2831 | for (cur = p->cond_list; cur; cur = cur->next) { | 2957 | for (cur = policydb->cond_list; cur; cur = cur->next) { |
2832 | rc = evaluate_cond_node(p, cur); | 2958 | rc = evaluate_cond_node(policydb, cur); |
2833 | if (rc) | 2959 | if (rc) |
2834 | goto out; | 2960 | goto out; |
2835 | } | 2961 | } |
@@ -2848,8 +2974,11 @@ out: | |||
2848 | * security_sid_mls_copy() - computes a new sid based on the given | 2974 | * security_sid_mls_copy() - computes a new sid based on the given |
2849 | * sid and the mls portion of mls_sid. | 2975 | * sid and the mls portion of mls_sid. |
2850 | */ | 2976 | */ |
2851 | int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | 2977 | int security_sid_mls_copy(struct selinux_state *state, |
2978 | u32 sid, u32 mls_sid, u32 *new_sid) | ||
2852 | { | 2979 | { |
2980 | struct policydb *policydb = &state->ss->policydb; | ||
2981 | struct sidtab *sidtab = &state->ss->sidtab; | ||
2853 | struct context *context1; | 2982 | struct context *context1; |
2854 | struct context *context2; | 2983 | struct context *context2; |
2855 | struct context newcon; | 2984 | struct context newcon; |
@@ -2858,17 +2987,17 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2858 | int rc; | 2987 | int rc; |
2859 | 2988 | ||
2860 | rc = 0; | 2989 | rc = 0; |
2861 | if (!ss_initialized || !policydb.mls_enabled) { | 2990 | if (!state->initialized || !policydb->mls_enabled) { |
2862 | *new_sid = sid; | 2991 | *new_sid = sid; |
2863 | goto out; | 2992 | goto out; |
2864 | } | 2993 | } |
2865 | 2994 | ||
2866 | context_init(&newcon); | 2995 | context_init(&newcon); |
2867 | 2996 | ||
2868 | read_lock(&policy_rwlock); | 2997 | read_lock(&state->ss->policy_rwlock); |
2869 | 2998 | ||
2870 | rc = -EINVAL; | 2999 | rc = -EINVAL; |
2871 | context1 = sidtab_search(&sidtab, sid); | 3000 | context1 = sidtab_search(sidtab, sid); |
2872 | if (!context1) { | 3001 | if (!context1) { |
2873 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 3002 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2874 | __func__, sid); | 3003 | __func__, sid); |
@@ -2876,7 +3005,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2876 | } | 3005 | } |
2877 | 3006 | ||
2878 | rc = -EINVAL; | 3007 | rc = -EINVAL; |
2879 | context2 = sidtab_search(&sidtab, mls_sid); | 3008 | context2 = sidtab_search(sidtab, mls_sid); |
2880 | if (!context2) { | 3009 | if (!context2) { |
2881 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 3010 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2882 | __func__, mls_sid); | 3011 | __func__, mls_sid); |
@@ -2891,10 +3020,11 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2891 | goto out_unlock; | 3020 | goto out_unlock; |
2892 | 3021 | ||
2893 | /* Check the validity of the new context. */ | 3022 | /* Check the validity of the new context. */ |
2894 | if (!policydb_context_isvalid(&policydb, &newcon)) { | 3023 | if (!policydb_context_isvalid(policydb, &newcon)) { |
2895 | rc = convert_context_handle_invalid_context(&newcon); | 3024 | rc = convert_context_handle_invalid_context(state, &newcon); |
2896 | if (rc) { | 3025 | if (rc) { |
2897 | if (!context_struct_to_string(&newcon, &s, &len)) { | 3026 | if (!context_struct_to_string(policydb, &newcon, &s, |
3027 | &len)) { | ||
2898 | audit_log(current->audit_context, | 3028 | audit_log(current->audit_context, |
2899 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | 3029 | GFP_ATOMIC, AUDIT_SELINUX_ERR, |
2900 | "op=security_sid_mls_copy " | 3030 | "op=security_sid_mls_copy " |
@@ -2905,9 +3035,9 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2905 | } | 3035 | } |
2906 | } | 3036 | } |
2907 | 3037 | ||
2908 | rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid); | 3038 | rc = sidtab_context_to_sid(sidtab, &newcon, new_sid); |
2909 | out_unlock: | 3039 | out_unlock: |
2910 | read_unlock(&policy_rwlock); | 3040 | read_unlock(&state->ss->policy_rwlock); |
2911 | context_destroy(&newcon); | 3041 | context_destroy(&newcon); |
2912 | out: | 3042 | out: |
2913 | return rc; | 3043 | return rc; |
@@ -2933,10 +3063,13 @@ out: | |||
2933 | * multiple, inconsistent labels | -<errno> | SECSID_NULL | 3063 | * multiple, inconsistent labels | -<errno> | SECSID_NULL |
2934 | * | 3064 | * |
2935 | */ | 3065 | */ |
2936 | int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | 3066 | int security_net_peersid_resolve(struct selinux_state *state, |
3067 | u32 nlbl_sid, u32 nlbl_type, | ||
2937 | u32 xfrm_sid, | 3068 | u32 xfrm_sid, |
2938 | u32 *peer_sid) | 3069 | u32 *peer_sid) |
2939 | { | 3070 | { |
3071 | struct policydb *policydb = &state->ss->policydb; | ||
3072 | struct sidtab *sidtab = &state->ss->sidtab; | ||
2940 | int rc; | 3073 | int rc; |
2941 | struct context *nlbl_ctx; | 3074 | struct context *nlbl_ctx; |
2942 | struct context *xfrm_ctx; | 3075 | struct context *xfrm_ctx; |
@@ -2958,23 +3091,25 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2958 | return 0; | 3091 | return 0; |
2959 | } | 3092 | } |
2960 | 3093 | ||
2961 | /* we don't need to check ss_initialized here since the only way both | 3094 | /* |
3095 | * We don't need to check initialized here since the only way both | ||
2962 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 3096 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
2963 | * security server was initialized and ss_initialized was true */ | 3097 | * security server was initialized and state->initialized was true. |
2964 | if (!policydb.mls_enabled) | 3098 | */ |
3099 | if (!policydb->mls_enabled) | ||
2965 | return 0; | 3100 | return 0; |
2966 | 3101 | ||
2967 | read_lock(&policy_rwlock); | 3102 | read_lock(&state->ss->policy_rwlock); |
2968 | 3103 | ||
2969 | rc = -EINVAL; | 3104 | rc = -EINVAL; |
2970 | nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); | 3105 | nlbl_ctx = sidtab_search(sidtab, nlbl_sid); |
2971 | if (!nlbl_ctx) { | 3106 | if (!nlbl_ctx) { |
2972 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 3107 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2973 | __func__, nlbl_sid); | 3108 | __func__, nlbl_sid); |
2974 | goto out; | 3109 | goto out; |
2975 | } | 3110 | } |
2976 | rc = -EINVAL; | 3111 | rc = -EINVAL; |
2977 | xfrm_ctx = sidtab_search(&sidtab, xfrm_sid); | 3112 | xfrm_ctx = sidtab_search(sidtab, xfrm_sid); |
2978 | if (!xfrm_ctx) { | 3113 | if (!xfrm_ctx) { |
2979 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 3114 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2980 | __func__, xfrm_sid); | 3115 | __func__, xfrm_sid); |
@@ -2991,7 +3126,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2991 | * expressive */ | 3126 | * expressive */ |
2992 | *peer_sid = xfrm_sid; | 3127 | *peer_sid = xfrm_sid; |
2993 | out: | 3128 | out: |
2994 | read_unlock(&policy_rwlock); | 3129 | read_unlock(&state->ss->policy_rwlock); |
2995 | return rc; | 3130 | return rc; |
2996 | } | 3131 | } |
2997 | 3132 | ||
@@ -3008,19 +3143,27 @@ static int get_classes_callback(void *k, void *d, void *args) | |||
3008 | return 0; | 3143 | return 0; |
3009 | } | 3144 | } |
3010 | 3145 | ||
3011 | int security_get_classes(char ***classes, int *nclasses) | 3146 | int security_get_classes(struct selinux_state *state, |
3147 | char ***classes, int *nclasses) | ||
3012 | { | 3148 | { |
3149 | struct policydb *policydb = &state->ss->policydb; | ||
3013 | int rc; | 3150 | int rc; |
3014 | 3151 | ||
3015 | read_lock(&policy_rwlock); | 3152 | if (!state->initialized) { |
3153 | *nclasses = 0; | ||
3154 | *classes = NULL; | ||
3155 | return 0; | ||
3156 | } | ||
3157 | |||
3158 | read_lock(&state->ss->policy_rwlock); | ||
3016 | 3159 | ||
3017 | rc = -ENOMEM; | 3160 | rc = -ENOMEM; |
3018 | *nclasses = policydb.p_classes.nprim; | 3161 | *nclasses = policydb->p_classes.nprim; |
3019 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); | 3162 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
3020 | if (!*classes) | 3163 | if (!*classes) |
3021 | goto out; | 3164 | goto out; |
3022 | 3165 | ||
3023 | rc = hashtab_map(policydb.p_classes.table, get_classes_callback, | 3166 | rc = hashtab_map(policydb->p_classes.table, get_classes_callback, |
3024 | *classes); | 3167 | *classes); |
3025 | if (rc) { | 3168 | if (rc) { |
3026 | int i; | 3169 | int i; |
@@ -3030,7 +3173,7 @@ int security_get_classes(char ***classes, int *nclasses) | |||
3030 | } | 3173 | } |
3031 | 3174 | ||
3032 | out: | 3175 | out: |
3033 | read_unlock(&policy_rwlock); | 3176 | read_unlock(&state->ss->policy_rwlock); |
3034 | return rc; | 3177 | return rc; |
3035 | } | 3178 | } |
3036 | 3179 | ||
@@ -3047,15 +3190,17 @@ static int get_permissions_callback(void *k, void *d, void *args) | |||
3047 | return 0; | 3190 | return 0; |
3048 | } | 3191 | } |
3049 | 3192 | ||
3050 | int security_get_permissions(char *class, char ***perms, int *nperms) | 3193 | int security_get_permissions(struct selinux_state *state, |
3194 | char *class, char ***perms, int *nperms) | ||
3051 | { | 3195 | { |
3196 | struct policydb *policydb = &state->ss->policydb; | ||
3052 | int rc, i; | 3197 | int rc, i; |
3053 | struct class_datum *match; | 3198 | struct class_datum *match; |
3054 | 3199 | ||
3055 | read_lock(&policy_rwlock); | 3200 | read_lock(&state->ss->policy_rwlock); |
3056 | 3201 | ||
3057 | rc = -EINVAL; | 3202 | rc = -EINVAL; |
3058 | match = hashtab_search(policydb.p_classes.table, class); | 3203 | match = hashtab_search(policydb->p_classes.table, class); |
3059 | if (!match) { | 3204 | if (!match) { |
3060 | printk(KERN_ERR "SELinux: %s: unrecognized class %s\n", | 3205 | printk(KERN_ERR "SELinux: %s: unrecognized class %s\n", |
3061 | __func__, class); | 3206 | __func__, class); |
@@ -3081,25 +3226,25 @@ int security_get_permissions(char *class, char ***perms, int *nperms) | |||
3081 | goto err; | 3226 | goto err; |
3082 | 3227 | ||
3083 | out: | 3228 | out: |
3084 | read_unlock(&policy_rwlock); | 3229 | read_unlock(&state->ss->policy_rwlock); |
3085 | return rc; | 3230 | return rc; |
3086 | 3231 | ||
3087 | err: | 3232 | err: |
3088 | read_unlock(&policy_rwlock); | 3233 | read_unlock(&state->ss->policy_rwlock); |
3089 | for (i = 0; i < *nperms; i++) | 3234 | for (i = 0; i < *nperms; i++) |
3090 | kfree((*perms)[i]); | 3235 | kfree((*perms)[i]); |
3091 | kfree(*perms); | 3236 | kfree(*perms); |
3092 | return rc; | 3237 | return rc; |
3093 | } | 3238 | } |
3094 | 3239 | ||
3095 | int security_get_reject_unknown(void) | 3240 | int security_get_reject_unknown(struct selinux_state *state) |
3096 | { | 3241 | { |
3097 | return policydb.reject_unknown; | 3242 | return state->ss->policydb.reject_unknown; |
3098 | } | 3243 | } |
3099 | 3244 | ||
3100 | int security_get_allow_unknown(void) | 3245 | int security_get_allow_unknown(struct selinux_state *state) |
3101 | { | 3246 | { |
3102 | return policydb.allow_unknown; | 3247 | return state->ss->policydb.allow_unknown; |
3103 | } | 3248 | } |
3104 | 3249 | ||
3105 | /** | 3250 | /** |
@@ -3112,13 +3257,15 @@ int security_get_allow_unknown(void) | |||
3112 | * supported, false (0) if it isn't supported. | 3257 | * supported, false (0) if it isn't supported. |
3113 | * | 3258 | * |
3114 | */ | 3259 | */ |
3115 | int security_policycap_supported(unsigned int req_cap) | 3260 | int security_policycap_supported(struct selinux_state *state, |
3261 | unsigned int req_cap) | ||
3116 | { | 3262 | { |
3263 | struct policydb *policydb = &state->ss->policydb; | ||
3117 | int rc; | 3264 | int rc; |
3118 | 3265 | ||
3119 | read_lock(&policy_rwlock); | 3266 | read_lock(&state->ss->policy_rwlock); |
3120 | rc = ebitmap_get_bit(&policydb.policycaps, req_cap); | 3267 | rc = ebitmap_get_bit(&policydb->policycaps, req_cap); |
3121 | read_unlock(&policy_rwlock); | 3268 | read_unlock(&state->ss->policy_rwlock); |
3122 | 3269 | ||
3123 | return rc; | 3270 | return rc; |
3124 | } | 3271 | } |
@@ -3140,6 +3287,8 @@ void selinux_audit_rule_free(void *vrule) | |||
3140 | 3287 | ||
3141 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | 3288 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) |
3142 | { | 3289 | { |
3290 | struct selinux_state *state = &selinux_state; | ||
3291 | struct policydb *policydb = &state->ss->policydb; | ||
3143 | struct selinux_audit_rule *tmprule; | 3292 | struct selinux_audit_rule *tmprule; |
3144 | struct role_datum *roledatum; | 3293 | struct role_datum *roledatum; |
3145 | struct type_datum *typedatum; | 3294 | struct type_datum *typedatum; |
@@ -3149,7 +3298,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3149 | 3298 | ||
3150 | *rule = NULL; | 3299 | *rule = NULL; |
3151 | 3300 | ||
3152 | if (!ss_initialized) | 3301 | if (!state->initialized) |
3153 | return -EOPNOTSUPP; | 3302 | return -EOPNOTSUPP; |
3154 | 3303 | ||
3155 | switch (field) { | 3304 | switch (field) { |
@@ -3182,15 +3331,15 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3182 | 3331 | ||
3183 | context_init(&tmprule->au_ctxt); | 3332 | context_init(&tmprule->au_ctxt); |
3184 | 3333 | ||
3185 | read_lock(&policy_rwlock); | 3334 | read_lock(&state->ss->policy_rwlock); |
3186 | 3335 | ||
3187 | tmprule->au_seqno = latest_granting; | 3336 | tmprule->au_seqno = state->ss->latest_granting; |
3188 | 3337 | ||
3189 | switch (field) { | 3338 | switch (field) { |
3190 | case AUDIT_SUBJ_USER: | 3339 | case AUDIT_SUBJ_USER: |
3191 | case AUDIT_OBJ_USER: | 3340 | case AUDIT_OBJ_USER: |
3192 | rc = -EINVAL; | 3341 | rc = -EINVAL; |
3193 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | 3342 | userdatum = hashtab_search(policydb->p_users.table, rulestr); |
3194 | if (!userdatum) | 3343 | if (!userdatum) |
3195 | goto out; | 3344 | goto out; |
3196 | tmprule->au_ctxt.user = userdatum->value; | 3345 | tmprule->au_ctxt.user = userdatum->value; |
@@ -3198,7 +3347,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3198 | case AUDIT_SUBJ_ROLE: | 3347 | case AUDIT_SUBJ_ROLE: |
3199 | case AUDIT_OBJ_ROLE: | 3348 | case AUDIT_OBJ_ROLE: |
3200 | rc = -EINVAL; | 3349 | rc = -EINVAL; |
3201 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | 3350 | roledatum = hashtab_search(policydb->p_roles.table, rulestr); |
3202 | if (!roledatum) | 3351 | if (!roledatum) |
3203 | goto out; | 3352 | goto out; |
3204 | tmprule->au_ctxt.role = roledatum->value; | 3353 | tmprule->au_ctxt.role = roledatum->value; |
@@ -3206,7 +3355,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3206 | case AUDIT_SUBJ_TYPE: | 3355 | case AUDIT_SUBJ_TYPE: |
3207 | case AUDIT_OBJ_TYPE: | 3356 | case AUDIT_OBJ_TYPE: |
3208 | rc = -EINVAL; | 3357 | rc = -EINVAL; |
3209 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | 3358 | typedatum = hashtab_search(policydb->p_types.table, rulestr); |
3210 | if (!typedatum) | 3359 | if (!typedatum) |
3211 | goto out; | 3360 | goto out; |
3212 | tmprule->au_ctxt.type = typedatum->value; | 3361 | tmprule->au_ctxt.type = typedatum->value; |
@@ -3215,14 +3364,15 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3215 | case AUDIT_SUBJ_CLR: | 3364 | case AUDIT_SUBJ_CLR: |
3216 | case AUDIT_OBJ_LEV_LOW: | 3365 | case AUDIT_OBJ_LEV_LOW: |
3217 | case AUDIT_OBJ_LEV_HIGH: | 3366 | case AUDIT_OBJ_LEV_HIGH: |
3218 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | 3367 | rc = mls_from_string(policydb, rulestr, &tmprule->au_ctxt, |
3368 | GFP_ATOMIC); | ||
3219 | if (rc) | 3369 | if (rc) |
3220 | goto out; | 3370 | goto out; |
3221 | break; | 3371 | break; |
3222 | } | 3372 | } |
3223 | rc = 0; | 3373 | rc = 0; |
3224 | out: | 3374 | out: |
3225 | read_unlock(&policy_rwlock); | 3375 | read_unlock(&state->ss->policy_rwlock); |
3226 | 3376 | ||
3227 | if (rc) { | 3377 | if (rc) { |
3228 | selinux_audit_rule_free(tmprule); | 3378 | selinux_audit_rule_free(tmprule); |
@@ -3262,6 +3412,7 @@ int selinux_audit_rule_known(struct audit_krule *rule) | |||
3262 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | 3412 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, |
3263 | struct audit_context *actx) | 3413 | struct audit_context *actx) |
3264 | { | 3414 | { |
3415 | struct selinux_state *state = &selinux_state; | ||
3265 | struct context *ctxt; | 3416 | struct context *ctxt; |
3266 | struct mls_level *level; | 3417 | struct mls_level *level; |
3267 | struct selinux_audit_rule *rule = vrule; | 3418 | struct selinux_audit_rule *rule = vrule; |
@@ -3272,14 +3423,14 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
3272 | return -ENOENT; | 3423 | return -ENOENT; |
3273 | } | 3424 | } |
3274 | 3425 | ||
3275 | read_lock(&policy_rwlock); | 3426 | read_lock(&state->ss->policy_rwlock); |
3276 | 3427 | ||
3277 | if (rule->au_seqno < latest_granting) { | 3428 | if (rule->au_seqno < state->ss->latest_granting) { |
3278 | match = -ESTALE; | 3429 | match = -ESTALE; |
3279 | goto out; | 3430 | goto out; |
3280 | } | 3431 | } |
3281 | 3432 | ||
3282 | ctxt = sidtab_search(&sidtab, sid); | 3433 | ctxt = sidtab_search(&state->ss->sidtab, sid); |
3283 | if (unlikely(!ctxt)) { | 3434 | if (unlikely(!ctxt)) { |
3284 | WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", | 3435 | WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", |
3285 | sid); | 3436 | sid); |
@@ -3363,7 +3514,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
3363 | } | 3514 | } |
3364 | 3515 | ||
3365 | out: | 3516 | out: |
3366 | read_unlock(&policy_rwlock); | 3517 | read_unlock(&state->ss->policy_rwlock); |
3367 | return match; | 3518 | return match; |
3368 | } | 3519 | } |
3369 | 3520 | ||
@@ -3437,19 +3588,22 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, | |||
3437 | * failure. | 3588 | * failure. |
3438 | * | 3589 | * |
3439 | */ | 3590 | */ |
3440 | int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | 3591 | int security_netlbl_secattr_to_sid(struct selinux_state *state, |
3592 | struct netlbl_lsm_secattr *secattr, | ||
3441 | u32 *sid) | 3593 | u32 *sid) |
3442 | { | 3594 | { |
3595 | struct policydb *policydb = &state->ss->policydb; | ||
3596 | struct sidtab *sidtab = &state->ss->sidtab; | ||
3443 | int rc; | 3597 | int rc; |
3444 | struct context *ctx; | 3598 | struct context *ctx; |
3445 | struct context ctx_new; | 3599 | struct context ctx_new; |
3446 | 3600 | ||
3447 | if (!ss_initialized) { | 3601 | if (!state->initialized) { |
3448 | *sid = SECSID_NULL; | 3602 | *sid = SECSID_NULL; |
3449 | return 0; | 3603 | return 0; |
3450 | } | 3604 | } |
3451 | 3605 | ||
3452 | read_lock(&policy_rwlock); | 3606 | read_lock(&state->ss->policy_rwlock); |
3453 | 3607 | ||
3454 | if (secattr->flags & NETLBL_SECATTR_CACHE) | 3608 | if (secattr->flags & NETLBL_SECATTR_CACHE) |
3455 | *sid = *(u32 *)secattr->cache->data; | 3609 | *sid = *(u32 *)secattr->cache->data; |
@@ -3457,7 +3611,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
3457 | *sid = secattr->attr.secid; | 3611 | *sid = secattr->attr.secid; |
3458 | else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { | 3612 | else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { |
3459 | rc = -EIDRM; | 3613 | rc = -EIDRM; |
3460 | ctx = sidtab_search(&sidtab, SECINITSID_NETMSG); | 3614 | ctx = sidtab_search(sidtab, SECINITSID_NETMSG); |
3461 | if (ctx == NULL) | 3615 | if (ctx == NULL) |
3462 | goto out; | 3616 | goto out; |
3463 | 3617 | ||
@@ -3465,17 +3619,17 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
3465 | ctx_new.user = ctx->user; | 3619 | ctx_new.user = ctx->user; |
3466 | ctx_new.role = ctx->role; | 3620 | ctx_new.role = ctx->role; |
3467 | ctx_new.type = ctx->type; | 3621 | ctx_new.type = ctx->type; |
3468 | mls_import_netlbl_lvl(&ctx_new, secattr); | 3622 | mls_import_netlbl_lvl(policydb, &ctx_new, secattr); |
3469 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | 3623 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { |
3470 | rc = mls_import_netlbl_cat(&ctx_new, secattr); | 3624 | rc = mls_import_netlbl_cat(policydb, &ctx_new, secattr); |
3471 | if (rc) | 3625 | if (rc) |
3472 | goto out; | 3626 | goto out; |
3473 | } | 3627 | } |
3474 | rc = -EIDRM; | 3628 | rc = -EIDRM; |
3475 | if (!mls_context_isvalid(&policydb, &ctx_new)) | 3629 | if (!mls_context_isvalid(policydb, &ctx_new)) |
3476 | goto out_free; | 3630 | goto out_free; |
3477 | 3631 | ||
3478 | rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); | 3632 | rc = sidtab_context_to_sid(sidtab, &ctx_new, sid); |
3479 | if (rc) | 3633 | if (rc) |
3480 | goto out_free; | 3634 | goto out_free; |
3481 | 3635 | ||
@@ -3485,12 +3639,12 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
3485 | } else | 3639 | } else |
3486 | *sid = SECSID_NULL; | 3640 | *sid = SECSID_NULL; |
3487 | 3641 | ||
3488 | read_unlock(&policy_rwlock); | 3642 | read_unlock(&state->ss->policy_rwlock); |
3489 | return 0; | 3643 | return 0; |
3490 | out_free: | 3644 | out_free: |
3491 | ebitmap_destroy(&ctx_new.range.level[0].cat); | 3645 | ebitmap_destroy(&ctx_new.range.level[0].cat); |
3492 | out: | 3646 | out: |
3493 | read_unlock(&policy_rwlock); | 3647 | read_unlock(&state->ss->policy_rwlock); |
3494 | return rc; | 3648 | return rc; |
3495 | } | 3649 | } |
3496 | 3650 | ||
@@ -3504,33 +3658,35 @@ out: | |||
3504 | * Returns zero on success, negative values on failure. | 3658 | * Returns zero on success, negative values on failure. |
3505 | * | 3659 | * |
3506 | */ | 3660 | */ |
3507 | int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) | 3661 | int security_netlbl_sid_to_secattr(struct selinux_state *state, |
3662 | u32 sid, struct netlbl_lsm_secattr *secattr) | ||
3508 | { | 3663 | { |
3664 | struct policydb *policydb = &state->ss->policydb; | ||
3509 | int rc; | 3665 | int rc; |
3510 | struct context *ctx; | 3666 | struct context *ctx; |
3511 | 3667 | ||
3512 | if (!ss_initialized) | 3668 | if (!state->initialized) |
3513 | return 0; | 3669 | return 0; |
3514 | 3670 | ||
3515 | read_lock(&policy_rwlock); | 3671 | read_lock(&state->ss->policy_rwlock); |
3516 | 3672 | ||
3517 | rc = -ENOENT; | 3673 | rc = -ENOENT; |
3518 | ctx = sidtab_search(&sidtab, sid); | 3674 | ctx = sidtab_search(&state->ss->sidtab, sid); |
3519 | if (ctx == NULL) | 3675 | if (ctx == NULL) |
3520 | goto out; | 3676 | goto out; |
3521 | 3677 | ||
3522 | rc = -ENOMEM; | 3678 | rc = -ENOMEM; |
3523 | secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1), | 3679 | secattr->domain = kstrdup(sym_name(policydb, SYM_TYPES, ctx->type - 1), |
3524 | GFP_ATOMIC); | 3680 | GFP_ATOMIC); |
3525 | if (secattr->domain == NULL) | 3681 | if (secattr->domain == NULL) |
3526 | goto out; | 3682 | goto out; |
3527 | 3683 | ||
3528 | secattr->attr.secid = sid; | 3684 | secattr->attr.secid = sid; |
3529 | secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; | 3685 | secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; |
3530 | mls_export_netlbl_lvl(ctx, secattr); | 3686 | mls_export_netlbl_lvl(policydb, ctx, secattr); |
3531 | rc = mls_export_netlbl_cat(ctx, secattr); | 3687 | rc = mls_export_netlbl_cat(policydb, ctx, secattr); |
3532 | out: | 3688 | out: |
3533 | read_unlock(&policy_rwlock); | 3689 | read_unlock(&state->ss->policy_rwlock); |
3534 | return rc; | 3690 | return rc; |
3535 | } | 3691 | } |
3536 | #endif /* CONFIG_NETLABEL */ | 3692 | #endif /* CONFIG_NETLABEL */ |
@@ -3541,15 +3697,17 @@ out: | |||
3541 | * @len: length of data in bytes | 3697 | * @len: length of data in bytes |
3542 | * | 3698 | * |
3543 | */ | 3699 | */ |
3544 | int security_read_policy(void **data, size_t *len) | 3700 | int security_read_policy(struct selinux_state *state, |
3701 | void **data, size_t *len) | ||
3545 | { | 3702 | { |
3703 | struct policydb *policydb = &state->ss->policydb; | ||
3546 | int rc; | 3704 | int rc; |
3547 | struct policy_file fp; | 3705 | struct policy_file fp; |
3548 | 3706 | ||
3549 | if (!ss_initialized) | 3707 | if (!state->initialized) |
3550 | return -EINVAL; | 3708 | return -EINVAL; |
3551 | 3709 | ||
3552 | *len = security_policydb_len(); | 3710 | *len = security_policydb_len(state); |
3553 | 3711 | ||
3554 | *data = vmalloc_user(*len); | 3712 | *data = vmalloc_user(*len); |
3555 | if (!*data) | 3713 | if (!*data) |
@@ -3558,9 +3716,9 @@ int security_read_policy(void **data, size_t *len) | |||
3558 | fp.data = *data; | 3716 | fp.data = *data; |
3559 | fp.len = *len; | 3717 | fp.len = *len; |
3560 | 3718 | ||
3561 | read_lock(&policy_rwlock); | 3719 | read_lock(&state->ss->policy_rwlock); |
3562 | rc = policydb_write(&policydb, &fp); | 3720 | rc = policydb_write(policydb, &fp); |
3563 | read_unlock(&policy_rwlock); | 3721 | read_unlock(&state->ss->policy_rwlock); |
3564 | 3722 | ||
3565 | if (rc) | 3723 | if (rc) |
3566 | return rc; | 3724 | return rc; |
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index 356bdd36cf6d..24c7bdcc8075 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h | |||
@@ -10,7 +10,28 @@ | |||
10 | #include "policydb.h" | 10 | #include "policydb.h" |
11 | #include "sidtab.h" | 11 | #include "sidtab.h" |
12 | 12 | ||
13 | extern struct policydb policydb; | 13 | /* Mapping for a single class */ |
14 | struct selinux_mapping { | ||
15 | u16 value; /* policy value for class */ | ||
16 | unsigned int num_perms; /* number of permissions in class */ | ||
17 | u32 perms[sizeof(u32) * 8]; /* policy values for permissions */ | ||
18 | }; | ||
19 | |||
20 | /* Map for all of the classes, with array size */ | ||
21 | struct selinux_map { | ||
22 | struct selinux_mapping *mapping; /* indexed by class */ | ||
23 | u16 size; /* array size of mapping */ | ||
24 | }; | ||
25 | |||
26 | struct selinux_ss { | ||
27 | struct sidtab sidtab; | ||
28 | struct policydb policydb; | ||
29 | rwlock_t policy_rwlock; | ||
30 | u32 latest_granting; | ||
31 | struct selinux_map map; | ||
32 | struct page *status_page; | ||
33 | struct mutex status_lock; | ||
34 | }; | ||
14 | 35 | ||
15 | void services_compute_xperms_drivers(struct extended_perms *xperms, | 36 | void services_compute_xperms_drivers(struct extended_perms *xperms, |
16 | struct avtab_node *node); | 37 | struct avtab_node *node); |
@@ -19,4 +40,3 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, | |||
19 | struct avtab_node *node); | 40 | struct avtab_node *node); |
20 | 41 | ||
21 | #endif /* _SS_SERVICES_H_ */ | 42 | #endif /* _SS_SERVICES_H_ */ |
22 | |||
diff --git a/security/selinux/ss/status.c b/security/selinux/ss/status.c index d982365f9d1a..a121de45ac0e 100644 --- a/security/selinux/ss/status.c +++ b/security/selinux/ss/status.c | |||
@@ -35,8 +35,6 @@ | |||
35 | * In most cases, application shall confirm the kernel status is not | 35 | * In most cases, application shall confirm the kernel status is not |
36 | * changed without any system call invocations. | 36 | * changed without any system call invocations. |
37 | */ | 37 | */ |
38 | static struct page *selinux_status_page; | ||
39 | static DEFINE_MUTEX(selinux_status_lock); | ||
40 | 38 | ||
41 | /* | 39 | /* |
42 | * selinux_kernel_status_page | 40 | * selinux_kernel_status_page |
@@ -44,21 +42,21 @@ static DEFINE_MUTEX(selinux_status_lock); | |||
44 | * It returns a reference to selinux_status_page. If the status page is | 42 | * It returns a reference to selinux_status_page. If the status page is |
45 | * not allocated yet, it also tries to allocate it at the first time. | 43 | * not allocated yet, it also tries to allocate it at the first time. |
46 | */ | 44 | */ |
47 | struct page *selinux_kernel_status_page(void) | 45 | struct page *selinux_kernel_status_page(struct selinux_state *state) |
48 | { | 46 | { |
49 | struct selinux_kernel_status *status; | 47 | struct selinux_kernel_status *status; |
50 | struct page *result = NULL; | 48 | struct page *result = NULL; |
51 | 49 | ||
52 | mutex_lock(&selinux_status_lock); | 50 | mutex_lock(&state->ss->status_lock); |
53 | if (!selinux_status_page) { | 51 | if (!state->ss->status_page) { |
54 | selinux_status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); | 52 | state->ss->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); |
55 | 53 | ||
56 | if (selinux_status_page) { | 54 | if (state->ss->status_page) { |
57 | status = page_address(selinux_status_page); | 55 | status = page_address(state->ss->status_page); |
58 | 56 | ||
59 | status->version = SELINUX_KERNEL_STATUS_VERSION; | 57 | status->version = SELINUX_KERNEL_STATUS_VERSION; |
60 | status->sequence = 0; | 58 | status->sequence = 0; |
61 | status->enforcing = selinux_enforcing; | 59 | status->enforcing = enforcing_enabled(state); |
62 | /* | 60 | /* |
63 | * NOTE: the next policyload event shall set | 61 | * NOTE: the next policyload event shall set |
64 | * a positive value on the status->policyload, | 62 | * a positive value on the status->policyload, |
@@ -66,11 +64,12 @@ struct page *selinux_kernel_status_page(void) | |||
66 | * So, application can know it was updated. | 64 | * So, application can know it was updated. |
67 | */ | 65 | */ |
68 | status->policyload = 0; | 66 | status->policyload = 0; |
69 | status->deny_unknown = !security_get_allow_unknown(); | 67 | status->deny_unknown = |
68 | !security_get_allow_unknown(state); | ||
70 | } | 69 | } |
71 | } | 70 | } |
72 | result = selinux_status_page; | 71 | result = state->ss->status_page; |
73 | mutex_unlock(&selinux_status_lock); | 72 | mutex_unlock(&state->ss->status_lock); |
74 | 73 | ||
75 | return result; | 74 | return result; |
76 | } | 75 | } |
@@ -80,13 +79,14 @@ struct page *selinux_kernel_status_page(void) | |||
80 | * | 79 | * |
81 | * It updates status of the current enforcing/permissive mode. | 80 | * It updates status of the current enforcing/permissive mode. |
82 | */ | 81 | */ |
83 | void selinux_status_update_setenforce(int enforcing) | 82 | void selinux_status_update_setenforce(struct selinux_state *state, |
83 | int enforcing) | ||
84 | { | 84 | { |
85 | struct selinux_kernel_status *status; | 85 | struct selinux_kernel_status *status; |
86 | 86 | ||
87 | mutex_lock(&selinux_status_lock); | 87 | mutex_lock(&state->ss->status_lock); |
88 | if (selinux_status_page) { | 88 | if (state->ss->status_page) { |
89 | status = page_address(selinux_status_page); | 89 | status = page_address(state->ss->status_page); |
90 | 90 | ||
91 | status->sequence++; | 91 | status->sequence++; |
92 | smp_wmb(); | 92 | smp_wmb(); |
@@ -96,7 +96,7 @@ void selinux_status_update_setenforce(int enforcing) | |||
96 | smp_wmb(); | 96 | smp_wmb(); |
97 | status->sequence++; | 97 | status->sequence++; |
98 | } | 98 | } |
99 | mutex_unlock(&selinux_status_lock); | 99 | mutex_unlock(&state->ss->status_lock); |
100 | } | 100 | } |
101 | 101 | ||
102 | /* | 102 | /* |
@@ -105,22 +105,23 @@ void selinux_status_update_setenforce(int enforcing) | |||
105 | * It updates status of the times of policy reloaded, and current | 105 | * It updates status of the times of policy reloaded, and current |
106 | * setting of deny_unknown. | 106 | * setting of deny_unknown. |
107 | */ | 107 | */ |
108 | void selinux_status_update_policyload(int seqno) | 108 | void selinux_status_update_policyload(struct selinux_state *state, |
109 | int seqno) | ||
109 | { | 110 | { |
110 | struct selinux_kernel_status *status; | 111 | struct selinux_kernel_status *status; |
111 | 112 | ||
112 | mutex_lock(&selinux_status_lock); | 113 | mutex_lock(&state->ss->status_lock); |
113 | if (selinux_status_page) { | 114 | if (state->ss->status_page) { |
114 | status = page_address(selinux_status_page); | 115 | status = page_address(state->ss->status_page); |
115 | 116 | ||
116 | status->sequence++; | 117 | status->sequence++; |
117 | smp_wmb(); | 118 | smp_wmb(); |
118 | 119 | ||
119 | status->policyload = seqno; | 120 | status->policyload = seqno; |
120 | status->deny_unknown = !security_get_allow_unknown(); | 121 | status->deny_unknown = !security_get_allow_unknown(state); |
121 | 122 | ||
122 | smp_wmb(); | 123 | smp_wmb(); |
123 | status->sequence++; | 124 | status->sequence++; |
124 | } | 125 | } |
125 | mutex_unlock(&selinux_status_lock); | 126 | mutex_unlock(&state->ss->status_lock); |
126 | } | 127 | } |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 928188902901..91dc3783ed94 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -101,11 +101,13 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, | |||
101 | ctx->ctx_len = str_len; | 101 | ctx->ctx_len = str_len; |
102 | memcpy(ctx->ctx_str, &uctx[1], str_len); | 102 | memcpy(ctx->ctx_str, &uctx[1], str_len); |
103 | ctx->ctx_str[str_len] = '\0'; | 103 | ctx->ctx_str[str_len] = '\0'; |
104 | rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid, gfp); | 104 | rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len, |
105 | &ctx->ctx_sid, gfp); | ||
105 | if (rc) | 106 | if (rc) |
106 | goto err; | 107 | goto err; |
107 | 108 | ||
108 | rc = avc_has_perm(tsec->sid, ctx->ctx_sid, | 109 | rc = avc_has_perm(&selinux_state, |
110 | tsec->sid, ctx->ctx_sid, | ||
109 | SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); | 111 | SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); |
110 | if (rc) | 112 | if (rc) |
111 | goto err; | 113 | goto err; |
@@ -141,7 +143,8 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) | |||
141 | if (!ctx) | 143 | if (!ctx) |
142 | return 0; | 144 | return 0; |
143 | 145 | ||
144 | return avc_has_perm(tsec->sid, ctx->ctx_sid, | 146 | return avc_has_perm(&selinux_state, |
147 | tsec->sid, ctx->ctx_sid, | ||
145 | SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, | 148 | SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, |
146 | NULL); | 149 | NULL); |
147 | } | 150 | } |
@@ -163,7 +166,8 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) | |||
163 | if (!selinux_authorizable_ctx(ctx)) | 166 | if (!selinux_authorizable_ctx(ctx)) |
164 | return -EINVAL; | 167 | return -EINVAL; |
165 | 168 | ||
166 | rc = avc_has_perm(fl_secid, ctx->ctx_sid, | 169 | rc = avc_has_perm(&selinux_state, |
170 | fl_secid, ctx->ctx_sid, | ||
167 | SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); | 171 | SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); |
168 | return (rc == -EACCES ? -ESRCH : rc); | 172 | return (rc == -EACCES ? -ESRCH : rc); |
169 | } | 173 | } |
@@ -202,7 +206,8 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
202 | /* We don't need a separate SA Vs. policy polmatch check since the SA | 206 | /* We don't need a separate SA Vs. policy polmatch check since the SA |
203 | * is now of the same label as the flow and a flow Vs. policy polmatch | 207 | * is now of the same label as the flow and a flow Vs. policy polmatch |
204 | * check had already happened in selinux_xfrm_policy_lookup() above. */ | 208 | * check had already happened in selinux_xfrm_policy_lookup() above. */ |
205 | return (avc_has_perm(fl->flowi_secid, state_sid, | 209 | return (avc_has_perm(&selinux_state, |
210 | fl->flowi_secid, state_sid, | ||
206 | SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, | 211 | SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, |
207 | NULL) ? 0 : 1); | 212 | NULL) ? 0 : 1); |
208 | } | 213 | } |
@@ -352,7 +357,8 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, | |||
352 | if (secid == 0) | 357 | if (secid == 0) |
353 | return -EINVAL; | 358 | return -EINVAL; |
354 | 359 | ||
355 | rc = security_sid_to_context(secid, &ctx_str, &str_len); | 360 | rc = security_sid_to_context(&selinux_state, secid, &ctx_str, |
361 | &str_len); | ||
356 | if (rc) | 362 | if (rc) |
357 | return rc; | 363 | return rc; |
358 | 364 | ||
@@ -420,7 +426,8 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, | |||
420 | /* This check even when there's no association involved is intended, | 426 | /* This check even when there's no association involved is intended, |
421 | * according to Trent Jaeger, to make sure a process can't engage in | 427 | * according to Trent Jaeger, to make sure a process can't engage in |
422 | * non-IPsec communication unless explicitly allowed by policy. */ | 428 | * non-IPsec communication unless explicitly allowed by policy. */ |
423 | return avc_has_perm(sk_sid, peer_sid, | 429 | return avc_has_perm(&selinux_state, |
430 | sk_sid, peer_sid, | ||
424 | SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); | 431 | SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); |
425 | } | 432 | } |
426 | 433 | ||
@@ -463,6 +470,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, | |||
463 | /* This check even when there's no association involved is intended, | 470 | /* This check even when there's no association involved is intended, |
464 | * according to Trent Jaeger, to make sure a process can't engage in | 471 | * according to Trent Jaeger, to make sure a process can't engage in |
465 | * non-IPsec communication unless explicitly allowed by policy. */ | 472 | * non-IPsec communication unless explicitly allowed by policy. */ |
466 | return avc_has_perm(sk_sid, SECINITSID_UNLABELED, | 473 | return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED, |
467 | SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); | 474 | SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); |
468 | } | 475 | } |