Commit fd778461524849afd035679030ae8e8873c72b81
1 parent
69f594a389
Exists in
master
and in
38 other branches
security: remove the security_netlink_recv hook as it is equivalent to capable()
Once upon a time netlink was not sync and we had to get the effective capabilities from the skb that was being received. Today we instead get the capabilities from the current task. This has rendered the entire purpose of the hook moot as it is now functionally equivalent to the capable() call. Signed-off-by: Eric Paris <eparis@redhat.com>
Showing 14 changed files with 10 additions and 58 deletions Inline Diff
- drivers/scsi/scsi_netlink.c
- include/linux/security.h
- kernel/audit.c
- net/core/rtnetlink.c
- net/decnet/netfilter/dn_rtmsg.c
- net/ipv4/netfilter/ip_queue.c
- net/ipv6/netfilter/ip6_queue.c
- net/netfilter/nfnetlink.c
- net/netlink/genetlink.c
- net/xfrm/xfrm_user.c
- security/capability.c
- security/commoncap.c
- security/security.c
- security/selinux/hooks.c
drivers/scsi/scsi_netlink.c
1 | /* | 1 | /* |
2 | * scsi_netlink.c - SCSI Transport Netlink Interface | 2 | * scsi_netlink.c - SCSI Transport Netlink Interface |
3 | * | 3 | * |
4 | * Copyright (C) 2006 James Smart, Emulex Corporation | 4 | * Copyright (C) 2006 James Smart, Emulex Corporation |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
23 | #include <linux/security.h> | 23 | #include <linux/security.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
27 | #include <net/netlink.h> | 27 | #include <net/netlink.h> |
28 | 28 | ||
29 | #include <scsi/scsi_netlink.h> | 29 | #include <scsi/scsi_netlink.h> |
30 | #include "scsi_priv.h" | 30 | #include "scsi_priv.h" |
31 | 31 | ||
32 | struct sock *scsi_nl_sock = NULL; | 32 | struct sock *scsi_nl_sock = NULL; |
33 | EXPORT_SYMBOL_GPL(scsi_nl_sock); | 33 | EXPORT_SYMBOL_GPL(scsi_nl_sock); |
34 | 34 | ||
35 | static DEFINE_SPINLOCK(scsi_nl_lock); | 35 | static DEFINE_SPINLOCK(scsi_nl_lock); |
36 | static struct list_head scsi_nl_drivers; | 36 | static struct list_head scsi_nl_drivers; |
37 | 37 | ||
38 | static u32 scsi_nl_state; | 38 | static u32 scsi_nl_state; |
39 | #define STATE_EHANDLER_BSY 0x00000001 | 39 | #define STATE_EHANDLER_BSY 0x00000001 |
40 | 40 | ||
41 | struct scsi_nl_transport { | 41 | struct scsi_nl_transport { |
42 | int (*msg_handler)(struct sk_buff *); | 42 | int (*msg_handler)(struct sk_buff *); |
43 | void (*event_handler)(struct notifier_block *, unsigned long, void *); | 43 | void (*event_handler)(struct notifier_block *, unsigned long, void *); |
44 | unsigned int refcnt; | 44 | unsigned int refcnt; |
45 | int flags; | 45 | int flags; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* flags values (bit flags) */ | 48 | /* flags values (bit flags) */ |
49 | #define HANDLER_DELETING 0x1 | 49 | #define HANDLER_DELETING 0x1 |
50 | 50 | ||
51 | static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = | 51 | static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = |
52 | { {NULL, }, }; | 52 | { {NULL, }, }; |
53 | 53 | ||
54 | 54 | ||
55 | struct scsi_nl_drvr { | 55 | struct scsi_nl_drvr { |
56 | struct list_head next; | 56 | struct list_head next; |
57 | int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, | 57 | int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, |
58 | u32 len, u32 pid); | 58 | u32 len, u32 pid); |
59 | void (*devt_handler)(struct notifier_block *nb, | 59 | void (*devt_handler)(struct notifier_block *nb, |
60 | unsigned long event, void *notify_ptr); | 60 | unsigned long event, void *notify_ptr); |
61 | struct scsi_host_template *hostt; | 61 | struct scsi_host_template *hostt; |
62 | u64 vendor_id; | 62 | u64 vendor_id; |
63 | unsigned int refcnt; | 63 | unsigned int refcnt; |
64 | int flags; | 64 | int flags; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | 67 | ||
68 | 68 | ||
69 | /** | 69 | /** |
70 | * scsi_nl_rcv_msg - Receive message handler. | 70 | * scsi_nl_rcv_msg - Receive message handler. |
71 | * @skb: socket receive buffer | 71 | * @skb: socket receive buffer |
72 | * | 72 | * |
73 | * Description: Extracts message from a receive buffer. | 73 | * Description: Extracts message from a receive buffer. |
74 | * Validates message header and calls appropriate transport message handler | 74 | * Validates message header and calls appropriate transport message handler |
75 | * | 75 | * |
76 | * | 76 | * |
77 | **/ | 77 | **/ |
78 | static void | 78 | static void |
79 | scsi_nl_rcv_msg(struct sk_buff *skb) | 79 | scsi_nl_rcv_msg(struct sk_buff *skb) |
80 | { | 80 | { |
81 | struct nlmsghdr *nlh; | 81 | struct nlmsghdr *nlh; |
82 | struct scsi_nl_hdr *hdr; | 82 | struct scsi_nl_hdr *hdr; |
83 | unsigned long flags; | 83 | unsigned long flags; |
84 | u32 rlen; | 84 | u32 rlen; |
85 | int err, tport; | 85 | int err, tport; |
86 | 86 | ||
87 | while (skb->len >= NLMSG_SPACE(0)) { | 87 | while (skb->len >= NLMSG_SPACE(0)) { |
88 | err = 0; | 88 | err = 0; |
89 | 89 | ||
90 | nlh = nlmsg_hdr(skb); | 90 | nlh = nlmsg_hdr(skb); |
91 | if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) || | 91 | if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) || |
92 | (skb->len < nlh->nlmsg_len)) { | 92 | (skb->len < nlh->nlmsg_len)) { |
93 | printk(KERN_WARNING "%s: discarding partial skb\n", | 93 | printk(KERN_WARNING "%s: discarding partial skb\n", |
94 | __func__); | 94 | __func__); |
95 | return; | 95 | return; |
96 | } | 96 | } |
97 | 97 | ||
98 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | 98 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); |
99 | if (rlen > skb->len) | 99 | if (rlen > skb->len) |
100 | rlen = skb->len; | 100 | rlen = skb->len; |
101 | 101 | ||
102 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { | 102 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { |
103 | err = -EBADMSG; | 103 | err = -EBADMSG; |
104 | goto next_msg; | 104 | goto next_msg; |
105 | } | 105 | } |
106 | 106 | ||
107 | hdr = NLMSG_DATA(nlh); | 107 | hdr = NLMSG_DATA(nlh); |
108 | if ((hdr->version != SCSI_NL_VERSION) || | 108 | if ((hdr->version != SCSI_NL_VERSION) || |
109 | (hdr->magic != SCSI_NL_MAGIC)) { | 109 | (hdr->magic != SCSI_NL_MAGIC)) { |
110 | err = -EPROTOTYPE; | 110 | err = -EPROTOTYPE; |
111 | goto next_msg; | 111 | goto next_msg; |
112 | } | 112 | } |
113 | 113 | ||
114 | if (security_netlink_recv(skb, CAP_SYS_ADMIN)) { | 114 | if (!capable(CAP_SYS_ADMIN)) { |
115 | err = -EPERM; | 115 | err = -EPERM; |
116 | goto next_msg; | 116 | goto next_msg; |
117 | } | 117 | } |
118 | 118 | ||
119 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { | 119 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { |
120 | printk(KERN_WARNING "%s: discarding partial message\n", | 120 | printk(KERN_WARNING "%s: discarding partial message\n", |
121 | __func__); | 121 | __func__); |
122 | goto next_msg; | 122 | goto next_msg; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Deliver message to the appropriate transport | 126 | * Deliver message to the appropriate transport |
127 | */ | 127 | */ |
128 | spin_lock_irqsave(&scsi_nl_lock, flags); | 128 | spin_lock_irqsave(&scsi_nl_lock, flags); |
129 | 129 | ||
130 | tport = hdr->transport; | 130 | tport = hdr->transport; |
131 | if ((tport < SCSI_NL_MAX_TRANSPORTS) && | 131 | if ((tport < SCSI_NL_MAX_TRANSPORTS) && |
132 | !(transports[tport].flags & HANDLER_DELETING) && | 132 | !(transports[tport].flags & HANDLER_DELETING) && |
133 | (transports[tport].msg_handler)) { | 133 | (transports[tport].msg_handler)) { |
134 | transports[tport].refcnt++; | 134 | transports[tport].refcnt++; |
135 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 135 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
136 | err = transports[tport].msg_handler(skb); | 136 | err = transports[tport].msg_handler(skb); |
137 | spin_lock_irqsave(&scsi_nl_lock, flags); | 137 | spin_lock_irqsave(&scsi_nl_lock, flags); |
138 | transports[tport].refcnt--; | 138 | transports[tport].refcnt--; |
139 | } else | 139 | } else |
140 | err = -ENOENT; | 140 | err = -ENOENT; |
141 | 141 | ||
142 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 142 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
143 | 143 | ||
144 | next_msg: | 144 | next_msg: |
145 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) | 145 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) |
146 | netlink_ack(skb, nlh, err); | 146 | netlink_ack(skb, nlh, err); |
147 | 147 | ||
148 | skb_pull(skb, rlen); | 148 | skb_pull(skb, rlen); |
149 | } | 149 | } |
150 | } | 150 | } |
151 | 151 | ||
152 | 152 | ||
153 | /** | 153 | /** |
154 | * scsi_nl_rcv_event - Event handler for a netlink socket. | 154 | * scsi_nl_rcv_event - Event handler for a netlink socket. |
155 | * @this: event notifier block | 155 | * @this: event notifier block |
156 | * @event: event type | 156 | * @event: event type |
157 | * @ptr: event payload | 157 | * @ptr: event payload |
158 | * | 158 | * |
159 | **/ | 159 | **/ |
160 | static int | 160 | static int |
161 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) | 161 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) |
162 | { | 162 | { |
163 | struct netlink_notify *n = ptr; | 163 | struct netlink_notify *n = ptr; |
164 | struct scsi_nl_drvr *driver; | 164 | struct scsi_nl_drvr *driver; |
165 | unsigned long flags; | 165 | unsigned long flags; |
166 | int tport; | 166 | int tport; |
167 | 167 | ||
168 | if (n->protocol != NETLINK_SCSITRANSPORT) | 168 | if (n->protocol != NETLINK_SCSITRANSPORT) |
169 | return NOTIFY_DONE; | 169 | return NOTIFY_DONE; |
170 | 170 | ||
171 | spin_lock_irqsave(&scsi_nl_lock, flags); | 171 | spin_lock_irqsave(&scsi_nl_lock, flags); |
172 | scsi_nl_state |= STATE_EHANDLER_BSY; | 172 | scsi_nl_state |= STATE_EHANDLER_BSY; |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * Pass event on to any transports that may be listening | 175 | * Pass event on to any transports that may be listening |
176 | */ | 176 | */ |
177 | for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { | 177 | for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { |
178 | if (!(transports[tport].flags & HANDLER_DELETING) && | 178 | if (!(transports[tport].flags & HANDLER_DELETING) && |
179 | (transports[tport].event_handler)) { | 179 | (transports[tport].event_handler)) { |
180 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 180 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
181 | transports[tport].event_handler(this, event, ptr); | 181 | transports[tport].event_handler(this, event, ptr); |
182 | spin_lock_irqsave(&scsi_nl_lock, flags); | 182 | spin_lock_irqsave(&scsi_nl_lock, flags); |
183 | } | 183 | } |
184 | } | 184 | } |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * Pass event on to any drivers that may be listening | 187 | * Pass event on to any drivers that may be listening |
188 | */ | 188 | */ |
189 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | 189 | list_for_each_entry(driver, &scsi_nl_drivers, next) { |
190 | if (!(driver->flags & HANDLER_DELETING) && | 190 | if (!(driver->flags & HANDLER_DELETING) && |
191 | (driver->devt_handler)) { | 191 | (driver->devt_handler)) { |
192 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 192 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
193 | driver->devt_handler(this, event, ptr); | 193 | driver->devt_handler(this, event, ptr); |
194 | spin_lock_irqsave(&scsi_nl_lock, flags); | 194 | spin_lock_irqsave(&scsi_nl_lock, flags); |
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | scsi_nl_state &= ~STATE_EHANDLER_BSY; | 198 | scsi_nl_state &= ~STATE_EHANDLER_BSY; |
199 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 199 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
200 | 200 | ||
201 | return NOTIFY_DONE; | 201 | return NOTIFY_DONE; |
202 | } | 202 | } |
203 | 203 | ||
204 | static struct notifier_block scsi_netlink_notifier = { | 204 | static struct notifier_block scsi_netlink_notifier = { |
205 | .notifier_call = scsi_nl_rcv_event, | 205 | .notifier_call = scsi_nl_rcv_event, |
206 | }; | 206 | }; |
207 | 207 | ||
208 | 208 | ||
209 | /* | 209 | /* |
210 | * GENERIC SCSI transport receive and event handlers | 210 | * GENERIC SCSI transport receive and event handlers |
211 | */ | 211 | */ |
212 | 212 | ||
213 | /** | 213 | /** |
214 | * scsi_generic_msg_handler - receive message handler for GENERIC transport messages | 214 | * scsi_generic_msg_handler - receive message handler for GENERIC transport messages |
215 | * @skb: socket receive buffer | 215 | * @skb: socket receive buffer |
216 | **/ | 216 | **/ |
217 | static int | 217 | static int |
218 | scsi_generic_msg_handler(struct sk_buff *skb) | 218 | scsi_generic_msg_handler(struct sk_buff *skb) |
219 | { | 219 | { |
220 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | 220 | struct nlmsghdr *nlh = nlmsg_hdr(skb); |
221 | struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); | 221 | struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); |
222 | struct scsi_nl_drvr *driver; | 222 | struct scsi_nl_drvr *driver; |
223 | struct Scsi_Host *shost; | 223 | struct Scsi_Host *shost; |
224 | unsigned long flags; | 224 | unsigned long flags; |
225 | int err = 0, match, pid; | 225 | int err = 0, match, pid; |
226 | 226 | ||
227 | pid = NETLINK_CREDS(skb)->pid; | 227 | pid = NETLINK_CREDS(skb)->pid; |
228 | 228 | ||
229 | switch (snlh->msgtype) { | 229 | switch (snlh->msgtype) { |
230 | case SCSI_NL_SHOST_VENDOR: | 230 | case SCSI_NL_SHOST_VENDOR: |
231 | { | 231 | { |
232 | struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); | 232 | struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); |
233 | 233 | ||
234 | /* Locate the driver that corresponds to the message */ | 234 | /* Locate the driver that corresponds to the message */ |
235 | spin_lock_irqsave(&scsi_nl_lock, flags); | 235 | spin_lock_irqsave(&scsi_nl_lock, flags); |
236 | match = 0; | 236 | match = 0; |
237 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | 237 | list_for_each_entry(driver, &scsi_nl_drivers, next) { |
238 | if (driver->vendor_id == msg->vendor_id) { | 238 | if (driver->vendor_id == msg->vendor_id) { |
239 | match = 1; | 239 | match = 1; |
240 | break; | 240 | break; |
241 | } | 241 | } |
242 | } | 242 | } |
243 | 243 | ||
244 | if ((!match) || (!driver->dmsg_handler)) { | 244 | if ((!match) || (!driver->dmsg_handler)) { |
245 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 245 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
246 | err = -ESRCH; | 246 | err = -ESRCH; |
247 | goto rcv_exit; | 247 | goto rcv_exit; |
248 | } | 248 | } |
249 | 249 | ||
250 | if (driver->flags & HANDLER_DELETING) { | 250 | if (driver->flags & HANDLER_DELETING) { |
251 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 251 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
252 | err = -ESHUTDOWN; | 252 | err = -ESHUTDOWN; |
253 | goto rcv_exit; | 253 | goto rcv_exit; |
254 | } | 254 | } |
255 | 255 | ||
256 | driver->refcnt++; | 256 | driver->refcnt++; |
257 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 257 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
258 | 258 | ||
259 | 259 | ||
260 | /* if successful, scsi_host_lookup takes a shost reference */ | 260 | /* if successful, scsi_host_lookup takes a shost reference */ |
261 | shost = scsi_host_lookup(msg->host_no); | 261 | shost = scsi_host_lookup(msg->host_no); |
262 | if (!shost) { | 262 | if (!shost) { |
263 | err = -ENODEV; | 263 | err = -ENODEV; |
264 | goto driver_exit; | 264 | goto driver_exit; |
265 | } | 265 | } |
266 | 266 | ||
267 | /* is this host owned by the vendor ? */ | 267 | /* is this host owned by the vendor ? */ |
268 | if (shost->hostt != driver->hostt) { | 268 | if (shost->hostt != driver->hostt) { |
269 | err = -EINVAL; | 269 | err = -EINVAL; |
270 | goto vendormsg_put; | 270 | goto vendormsg_put; |
271 | } | 271 | } |
272 | 272 | ||
273 | /* pass message on to the driver */ | 273 | /* pass message on to the driver */ |
274 | err = driver->dmsg_handler(shost, (void *)&msg[1], | 274 | err = driver->dmsg_handler(shost, (void *)&msg[1], |
275 | msg->vmsg_datalen, pid); | 275 | msg->vmsg_datalen, pid); |
276 | 276 | ||
277 | vendormsg_put: | 277 | vendormsg_put: |
278 | /* release reference by scsi_host_lookup */ | 278 | /* release reference by scsi_host_lookup */ |
279 | scsi_host_put(shost); | 279 | scsi_host_put(shost); |
280 | 280 | ||
281 | driver_exit: | 281 | driver_exit: |
282 | /* release our own reference on the registration object */ | 282 | /* release our own reference on the registration object */ |
283 | spin_lock_irqsave(&scsi_nl_lock, flags); | 283 | spin_lock_irqsave(&scsi_nl_lock, flags); |
284 | driver->refcnt--; | 284 | driver->refcnt--; |
285 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 285 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
286 | break; | 286 | break; |
287 | } | 287 | } |
288 | 288 | ||
289 | default: | 289 | default: |
290 | err = -EBADR; | 290 | err = -EBADR; |
291 | break; | 291 | break; |
292 | } | 292 | } |
293 | 293 | ||
294 | rcv_exit: | 294 | rcv_exit: |
295 | if (err) | 295 | if (err) |
296 | printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", | 296 | printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", |
297 | __func__, snlh->msgtype, err); | 297 | __func__, snlh->msgtype, err); |
298 | return err; | 298 | return err; |
299 | } | 299 | } |
300 | 300 | ||
301 | 301 | ||
302 | /** | 302 | /** |
303 | * scsi_nl_add_transport - | 303 | * scsi_nl_add_transport - |
304 | * Registers message and event handlers for a transport. Enables | 304 | * Registers message and event handlers for a transport. Enables |
305 | * receipt of netlink messages and events to a transport. | 305 | * receipt of netlink messages and events to a transport. |
306 | * | 306 | * |
307 | * @tport: transport registering handlers | 307 | * @tport: transport registering handlers |
308 | * @msg_handler: receive message handler callback | 308 | * @msg_handler: receive message handler callback |
309 | * @event_handler: receive event handler callback | 309 | * @event_handler: receive event handler callback |
310 | **/ | 310 | **/ |
311 | int | 311 | int |
312 | scsi_nl_add_transport(u8 tport, | 312 | scsi_nl_add_transport(u8 tport, |
313 | int (*msg_handler)(struct sk_buff *), | 313 | int (*msg_handler)(struct sk_buff *), |
314 | void (*event_handler)(struct notifier_block *, unsigned long, void *)) | 314 | void (*event_handler)(struct notifier_block *, unsigned long, void *)) |
315 | { | 315 | { |
316 | unsigned long flags; | 316 | unsigned long flags; |
317 | int err = 0; | 317 | int err = 0; |
318 | 318 | ||
319 | if (tport >= SCSI_NL_MAX_TRANSPORTS) | 319 | if (tport >= SCSI_NL_MAX_TRANSPORTS) |
320 | return -EINVAL; | 320 | return -EINVAL; |
321 | 321 | ||
322 | spin_lock_irqsave(&scsi_nl_lock, flags); | 322 | spin_lock_irqsave(&scsi_nl_lock, flags); |
323 | 323 | ||
324 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | 324 | if (scsi_nl_state & STATE_EHANDLER_BSY) { |
325 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 325 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
326 | msleep(1); | 326 | msleep(1); |
327 | spin_lock_irqsave(&scsi_nl_lock, flags); | 327 | spin_lock_irqsave(&scsi_nl_lock, flags); |
328 | } | 328 | } |
329 | 329 | ||
330 | if (transports[tport].msg_handler || transports[tport].event_handler) { | 330 | if (transports[tport].msg_handler || transports[tport].event_handler) { |
331 | err = -EALREADY; | 331 | err = -EALREADY; |
332 | goto register_out; | 332 | goto register_out; |
333 | } | 333 | } |
334 | 334 | ||
335 | transports[tport].msg_handler = msg_handler; | 335 | transports[tport].msg_handler = msg_handler; |
336 | transports[tport].event_handler = event_handler; | 336 | transports[tport].event_handler = event_handler; |
337 | transports[tport].flags = 0; | 337 | transports[tport].flags = 0; |
338 | transports[tport].refcnt = 0; | 338 | transports[tport].refcnt = 0; |
339 | 339 | ||
340 | register_out: | 340 | register_out: |
341 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 341 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
342 | 342 | ||
343 | return err; | 343 | return err; |
344 | } | 344 | } |
345 | EXPORT_SYMBOL_GPL(scsi_nl_add_transport); | 345 | EXPORT_SYMBOL_GPL(scsi_nl_add_transport); |
346 | 346 | ||
347 | 347 | ||
348 | /** | 348 | /** |
349 | * scsi_nl_remove_transport - | 349 | * scsi_nl_remove_transport - |
350 | * Disable transport receiption of messages and events | 350 | * Disable transport receiption of messages and events |
351 | * | 351 | * |
352 | * @tport: transport deregistering handlers | 352 | * @tport: transport deregistering handlers |
353 | * | 353 | * |
354 | **/ | 354 | **/ |
355 | void | 355 | void |
356 | scsi_nl_remove_transport(u8 tport) | 356 | scsi_nl_remove_transport(u8 tport) |
357 | { | 357 | { |
358 | unsigned long flags; | 358 | unsigned long flags; |
359 | 359 | ||
360 | spin_lock_irqsave(&scsi_nl_lock, flags); | 360 | spin_lock_irqsave(&scsi_nl_lock, flags); |
361 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | 361 | if (scsi_nl_state & STATE_EHANDLER_BSY) { |
362 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 362 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
363 | msleep(1); | 363 | msleep(1); |
364 | spin_lock_irqsave(&scsi_nl_lock, flags); | 364 | spin_lock_irqsave(&scsi_nl_lock, flags); |
365 | } | 365 | } |
366 | 366 | ||
367 | if (tport < SCSI_NL_MAX_TRANSPORTS) { | 367 | if (tport < SCSI_NL_MAX_TRANSPORTS) { |
368 | transports[tport].flags |= HANDLER_DELETING; | 368 | transports[tport].flags |= HANDLER_DELETING; |
369 | 369 | ||
370 | while (transports[tport].refcnt != 0) { | 370 | while (transports[tport].refcnt != 0) { |
371 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 371 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
372 | schedule_timeout_uninterruptible(HZ/4); | 372 | schedule_timeout_uninterruptible(HZ/4); |
373 | spin_lock_irqsave(&scsi_nl_lock, flags); | 373 | spin_lock_irqsave(&scsi_nl_lock, flags); |
374 | } | 374 | } |
375 | transports[tport].msg_handler = NULL; | 375 | transports[tport].msg_handler = NULL; |
376 | transports[tport].event_handler = NULL; | 376 | transports[tport].event_handler = NULL; |
377 | transports[tport].flags = 0; | 377 | transports[tport].flags = 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 380 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
381 | 381 | ||
382 | return; | 382 | return; |
383 | } | 383 | } |
384 | EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); | 384 | EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); |
385 | 385 | ||
386 | 386 | ||
387 | /** | 387 | /** |
388 | * scsi_nl_add_driver - | 388 | * scsi_nl_add_driver - |
389 | * A driver is registering its interfaces for SCSI netlink messages | 389 | * A driver is registering its interfaces for SCSI netlink messages |
390 | * | 390 | * |
391 | * @vendor_id: A unique identification value for the driver. | 391 | * @vendor_id: A unique identification value for the driver. |
392 | * @hostt: address of the driver's host template. Used | 392 | * @hostt: address of the driver's host template. Used |
393 | * to verify an shost is bound to the driver | 393 | * to verify an shost is bound to the driver |
394 | * @nlmsg_handler: receive message handler callback | 394 | * @nlmsg_handler: receive message handler callback |
395 | * @nlevt_handler: receive event handler callback | 395 | * @nlevt_handler: receive event handler callback |
396 | * | 396 | * |
397 | * Returns: | 397 | * Returns: |
398 | * 0 on Success | 398 | * 0 on Success |
399 | * error result otherwise | 399 | * error result otherwise |
400 | **/ | 400 | **/ |
401 | int | 401 | int |
402 | scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, | 402 | scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, |
403 | int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, | 403 | int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, |
404 | u32 len, u32 pid), | 404 | u32 len, u32 pid), |
405 | void (*nlevt_handler)(struct notifier_block *nb, | 405 | void (*nlevt_handler)(struct notifier_block *nb, |
406 | unsigned long event, void *notify_ptr)) | 406 | unsigned long event, void *notify_ptr)) |
407 | { | 407 | { |
408 | struct scsi_nl_drvr *driver; | 408 | struct scsi_nl_drvr *driver; |
409 | unsigned long flags; | 409 | unsigned long flags; |
410 | 410 | ||
411 | driver = kzalloc(sizeof(*driver), GFP_KERNEL); | 411 | driver = kzalloc(sizeof(*driver), GFP_KERNEL); |
412 | if (unlikely(!driver)) { | 412 | if (unlikely(!driver)) { |
413 | printk(KERN_ERR "%s: allocation failure\n", __func__); | 413 | printk(KERN_ERR "%s: allocation failure\n", __func__); |
414 | return -ENOMEM; | 414 | return -ENOMEM; |
415 | } | 415 | } |
416 | 416 | ||
417 | driver->dmsg_handler = nlmsg_handler; | 417 | driver->dmsg_handler = nlmsg_handler; |
418 | driver->devt_handler = nlevt_handler; | 418 | driver->devt_handler = nlevt_handler; |
419 | driver->hostt = hostt; | 419 | driver->hostt = hostt; |
420 | driver->vendor_id = vendor_id; | 420 | driver->vendor_id = vendor_id; |
421 | 421 | ||
422 | spin_lock_irqsave(&scsi_nl_lock, flags); | 422 | spin_lock_irqsave(&scsi_nl_lock, flags); |
423 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | 423 | if (scsi_nl_state & STATE_EHANDLER_BSY) { |
424 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 424 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
425 | msleep(1); | 425 | msleep(1); |
426 | spin_lock_irqsave(&scsi_nl_lock, flags); | 426 | spin_lock_irqsave(&scsi_nl_lock, flags); |
427 | } | 427 | } |
428 | list_add_tail(&driver->next, &scsi_nl_drivers); | 428 | list_add_tail(&driver->next, &scsi_nl_drivers); |
429 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 429 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
430 | 430 | ||
431 | return 0; | 431 | return 0; |
432 | } | 432 | } |
433 | EXPORT_SYMBOL_GPL(scsi_nl_add_driver); | 433 | EXPORT_SYMBOL_GPL(scsi_nl_add_driver); |
434 | 434 | ||
435 | 435 | ||
436 | /** | 436 | /** |
437 | * scsi_nl_remove_driver - | 437 | * scsi_nl_remove_driver - |
438 | * An driver is unregistering with the SCSI netlink messages | 438 | * An driver is unregistering with the SCSI netlink messages |
439 | * | 439 | * |
440 | * @vendor_id: The unique identification value for the driver. | 440 | * @vendor_id: The unique identification value for the driver. |
441 | **/ | 441 | **/ |
442 | void | 442 | void |
443 | scsi_nl_remove_driver(u64 vendor_id) | 443 | scsi_nl_remove_driver(u64 vendor_id) |
444 | { | 444 | { |
445 | struct scsi_nl_drvr *driver; | 445 | struct scsi_nl_drvr *driver; |
446 | unsigned long flags; | 446 | unsigned long flags; |
447 | 447 | ||
448 | spin_lock_irqsave(&scsi_nl_lock, flags); | 448 | spin_lock_irqsave(&scsi_nl_lock, flags); |
449 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | 449 | if (scsi_nl_state & STATE_EHANDLER_BSY) { |
450 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 450 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
451 | msleep(1); | 451 | msleep(1); |
452 | spin_lock_irqsave(&scsi_nl_lock, flags); | 452 | spin_lock_irqsave(&scsi_nl_lock, flags); |
453 | } | 453 | } |
454 | 454 | ||
455 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | 455 | list_for_each_entry(driver, &scsi_nl_drivers, next) { |
456 | if (driver->vendor_id == vendor_id) { | 456 | if (driver->vendor_id == vendor_id) { |
457 | driver->flags |= HANDLER_DELETING; | 457 | driver->flags |= HANDLER_DELETING; |
458 | while (driver->refcnt != 0) { | 458 | while (driver->refcnt != 0) { |
459 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 459 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
460 | schedule_timeout_uninterruptible(HZ/4); | 460 | schedule_timeout_uninterruptible(HZ/4); |
461 | spin_lock_irqsave(&scsi_nl_lock, flags); | 461 | spin_lock_irqsave(&scsi_nl_lock, flags); |
462 | } | 462 | } |
463 | list_del(&driver->next); | 463 | list_del(&driver->next); |
464 | kfree(driver); | 464 | kfree(driver); |
465 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 465 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
466 | return; | 466 | return; |
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | 470 | spin_unlock_irqrestore(&scsi_nl_lock, flags); |
471 | 471 | ||
472 | printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", | 472 | printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", |
473 | __func__, (unsigned long long)vendor_id); | 473 | __func__, (unsigned long long)vendor_id); |
474 | return; | 474 | return; |
475 | } | 475 | } |
476 | EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); | 476 | EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); |
477 | 477 | ||
478 | 478 | ||
479 | /** | 479 | /** |
480 | * scsi_netlink_init - Called by SCSI subsystem to initialize | 480 | * scsi_netlink_init - Called by SCSI subsystem to initialize |
481 | * the SCSI transport netlink interface | 481 | * the SCSI transport netlink interface |
482 | * | 482 | * |
483 | **/ | 483 | **/ |
484 | void | 484 | void |
485 | scsi_netlink_init(void) | 485 | scsi_netlink_init(void) |
486 | { | 486 | { |
487 | int error; | 487 | int error; |
488 | 488 | ||
489 | INIT_LIST_HEAD(&scsi_nl_drivers); | 489 | INIT_LIST_HEAD(&scsi_nl_drivers); |
490 | 490 | ||
491 | error = netlink_register_notifier(&scsi_netlink_notifier); | 491 | error = netlink_register_notifier(&scsi_netlink_notifier); |
492 | if (error) { | 492 | if (error) { |
493 | printk(KERN_ERR "%s: register of event handler failed - %d\n", | 493 | printk(KERN_ERR "%s: register of event handler failed - %d\n", |
494 | __func__, error); | 494 | __func__, error); |
495 | return; | 495 | return; |
496 | } | 496 | } |
497 | 497 | ||
498 | scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, | 498 | scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, |
499 | SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, | 499 | SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, |
500 | THIS_MODULE); | 500 | THIS_MODULE); |
501 | if (!scsi_nl_sock) { | 501 | if (!scsi_nl_sock) { |
502 | printk(KERN_ERR "%s: register of receive handler failed\n", | 502 | printk(KERN_ERR "%s: register of receive handler failed\n", |
503 | __func__); | 503 | __func__); |
504 | netlink_unregister_notifier(&scsi_netlink_notifier); | 504 | netlink_unregister_notifier(&scsi_netlink_notifier); |
505 | return; | 505 | return; |
506 | } | 506 | } |
507 | 507 | ||
508 | /* Register the entry points for the generic SCSI transport */ | 508 | /* Register the entry points for the generic SCSI transport */ |
509 | error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, | 509 | error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, |
510 | scsi_generic_msg_handler, NULL); | 510 | scsi_generic_msg_handler, NULL); |
511 | if (error) | 511 | if (error) |
512 | printk(KERN_ERR "%s: register of GENERIC transport handler" | 512 | printk(KERN_ERR "%s: register of GENERIC transport handler" |
513 | " failed - %d\n", __func__, error); | 513 | " failed - %d\n", __func__, error); |
514 | return; | 514 | return; |
515 | } | 515 | } |
516 | 516 | ||
517 | 517 | ||
518 | /** | 518 | /** |
519 | * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface | 519 | * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface |
520 | * | 520 | * |
521 | **/ | 521 | **/ |
522 | void | 522 | void |
523 | scsi_netlink_exit(void) | 523 | scsi_netlink_exit(void) |
524 | { | 524 | { |
525 | scsi_nl_remove_transport(SCSI_NL_TRANSPORT); | 525 | scsi_nl_remove_transport(SCSI_NL_TRANSPORT); |
526 | 526 | ||
527 | if (scsi_nl_sock) { | 527 | if (scsi_nl_sock) { |
528 | netlink_kernel_release(scsi_nl_sock); | 528 | netlink_kernel_release(scsi_nl_sock); |
529 | netlink_unregister_notifier(&scsi_netlink_notifier); | 529 | netlink_unregister_notifier(&scsi_netlink_notifier); |
530 | } | 530 | } |
531 | 531 | ||
532 | return; | 532 | return; |
533 | } | 533 | } |
534 | 534 | ||
535 | 535 | ||
536 | /* | 536 | /* |
537 | * Exported Interfaces | 537 | * Exported Interfaces |
538 | */ | 538 | */ |
539 | 539 | ||
540 | /** | 540 | /** |
541 | * scsi_nl_send_transport_msg - | 541 | * scsi_nl_send_transport_msg - |
542 | * Generic function to send a single message from a SCSI transport to | 542 | * Generic function to send a single message from a SCSI transport to |
543 | * a single process | 543 | * a single process |
544 | * | 544 | * |
545 | * @pid: receiving pid | 545 | * @pid: receiving pid |
546 | * @hdr: message payload | 546 | * @hdr: message payload |
547 | * | 547 | * |
548 | **/ | 548 | **/ |
549 | void | 549 | void |
550 | scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) | 550 | scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) |
551 | { | 551 | { |
552 | struct sk_buff *skb; | 552 | struct sk_buff *skb; |
553 | struct nlmsghdr *nlh; | 553 | struct nlmsghdr *nlh; |
554 | const char *fn; | 554 | const char *fn; |
555 | char *datab; | 555 | char *datab; |
556 | u32 len, skblen; | 556 | u32 len, skblen; |
557 | int err; | 557 | int err; |
558 | 558 | ||
559 | if (!scsi_nl_sock) { | 559 | if (!scsi_nl_sock) { |
560 | err = -ENOENT; | 560 | err = -ENOENT; |
561 | fn = "netlink socket"; | 561 | fn = "netlink socket"; |
562 | goto msg_fail; | 562 | goto msg_fail; |
563 | } | 563 | } |
564 | 564 | ||
565 | len = NLMSG_SPACE(hdr->msglen); | 565 | len = NLMSG_SPACE(hdr->msglen); |
566 | skblen = NLMSG_SPACE(len); | 566 | skblen = NLMSG_SPACE(len); |
567 | 567 | ||
568 | skb = alloc_skb(skblen, GFP_KERNEL); | 568 | skb = alloc_skb(skblen, GFP_KERNEL); |
569 | if (!skb) { | 569 | if (!skb) { |
570 | err = -ENOBUFS; | 570 | err = -ENOBUFS; |
571 | fn = "alloc_skb"; | 571 | fn = "alloc_skb"; |
572 | goto msg_fail; | 572 | goto msg_fail; |
573 | } | 573 | } |
574 | 574 | ||
575 | nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); | 575 | nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); |
576 | if (!nlh) { | 576 | if (!nlh) { |
577 | err = -ENOBUFS; | 577 | err = -ENOBUFS; |
578 | fn = "nlmsg_put"; | 578 | fn = "nlmsg_put"; |
579 | goto msg_fail_skb; | 579 | goto msg_fail_skb; |
580 | } | 580 | } |
581 | datab = NLMSG_DATA(nlh); | 581 | datab = NLMSG_DATA(nlh); |
582 | memcpy(datab, hdr, hdr->msglen); | 582 | memcpy(datab, hdr, hdr->msglen); |
583 | 583 | ||
584 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | 584 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); |
585 | if (err < 0) { | 585 | if (err < 0) { |
586 | fn = "nlmsg_unicast"; | 586 | fn = "nlmsg_unicast"; |
587 | /* nlmsg_unicast already kfree_skb'd */ | 587 | /* nlmsg_unicast already kfree_skb'd */ |
588 | goto msg_fail; | 588 | goto msg_fail; |
589 | } | 589 | } |
590 | 590 | ||
591 | return; | 591 | return; |
592 | 592 | ||
593 | msg_fail_skb: | 593 | msg_fail_skb: |
594 | kfree_skb(skb); | 594 | kfree_skb(skb); |
595 | msg_fail: | 595 | msg_fail: |
596 | printk(KERN_WARNING | 596 | printk(KERN_WARNING |
597 | "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " | 597 | "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " |
598 | "msglen %d: %s : err %d\n", | 598 | "msglen %d: %s : err %d\n", |
599 | __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, | 599 | __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, |
600 | fn, err); | 600 | fn, err); |
601 | return; | 601 | return; |
602 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); | 603 | EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); |
604 | 604 | ||
605 | 605 | ||
606 | /** | 606 | /** |
607 | * scsi_nl_send_vendor_msg - called to send a shost vendor unique message | 607 | * scsi_nl_send_vendor_msg - called to send a shost vendor unique message |
608 | * to a specific process id. | 608 | * to a specific process id. |
609 | * | 609 | * |
610 | * @pid: process id of the receiver | 610 | * @pid: process id of the receiver |
611 | * @host_no: host # sending the message | 611 | * @host_no: host # sending the message |
612 | * @vendor_id: unique identifier for the driver's vendor | 612 | * @vendor_id: unique identifier for the driver's vendor |
613 | * @data_len: amount, in bytes, of vendor unique payload data | 613 | * @data_len: amount, in bytes, of vendor unique payload data |
614 | * @data_buf: pointer to vendor unique data buffer | 614 | * @data_buf: pointer to vendor unique data buffer |
615 | * | 615 | * |
616 | * Returns: | 616 | * Returns: |
617 | * 0 on successful return | 617 | * 0 on successful return |
618 | * otherwise, failing error code | 618 | * otherwise, failing error code |
619 | * | 619 | * |
620 | * Notes: | 620 | * Notes: |
621 | * This routine assumes no locks are held on entry. | 621 | * This routine assumes no locks are held on entry. |
622 | */ | 622 | */ |
623 | int | 623 | int |
624 | scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, | 624 | scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, |
625 | char *data_buf, u32 data_len) | 625 | char *data_buf, u32 data_len) |
626 | { | 626 | { |
627 | struct sk_buff *skb; | 627 | struct sk_buff *skb; |
628 | struct nlmsghdr *nlh; | 628 | struct nlmsghdr *nlh; |
629 | struct scsi_nl_host_vendor_msg *msg; | 629 | struct scsi_nl_host_vendor_msg *msg; |
630 | u32 len, skblen; | 630 | u32 len, skblen; |
631 | int err; | 631 | int err; |
632 | 632 | ||
633 | if (!scsi_nl_sock) { | 633 | if (!scsi_nl_sock) { |
634 | err = -ENOENT; | 634 | err = -ENOENT; |
635 | goto send_vendor_fail; | 635 | goto send_vendor_fail; |
636 | } | 636 | } |
637 | 637 | ||
638 | len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); | 638 | len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); |
639 | skblen = NLMSG_SPACE(len); | 639 | skblen = NLMSG_SPACE(len); |
640 | 640 | ||
641 | skb = alloc_skb(skblen, GFP_KERNEL); | 641 | skb = alloc_skb(skblen, GFP_KERNEL); |
642 | if (!skb) { | 642 | if (!skb) { |
643 | err = -ENOBUFS; | 643 | err = -ENOBUFS; |
644 | goto send_vendor_fail; | 644 | goto send_vendor_fail; |
645 | } | 645 | } |
646 | 646 | ||
647 | nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, | 647 | nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, |
648 | skblen - sizeof(*nlh), 0); | 648 | skblen - sizeof(*nlh), 0); |
649 | if (!nlh) { | 649 | if (!nlh) { |
650 | err = -ENOBUFS; | 650 | err = -ENOBUFS; |
651 | goto send_vendor_fail_skb; | 651 | goto send_vendor_fail_skb; |
652 | } | 652 | } |
653 | msg = NLMSG_DATA(nlh); | 653 | msg = NLMSG_DATA(nlh); |
654 | 654 | ||
655 | INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, | 655 | INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, |
656 | SCSI_NL_SHOST_VENDOR, len); | 656 | SCSI_NL_SHOST_VENDOR, len); |
657 | msg->vendor_id = vendor_id; | 657 | msg->vendor_id = vendor_id; |
658 | msg->host_no = host_no; | 658 | msg->host_no = host_no; |
659 | msg->vmsg_datalen = data_len; /* bytes */ | 659 | msg->vmsg_datalen = data_len; /* bytes */ |
660 | memcpy(&msg[1], data_buf, data_len); | 660 | memcpy(&msg[1], data_buf, data_len); |
661 | 661 | ||
662 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | 662 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); |
663 | if (err) | 663 | if (err) |
664 | /* nlmsg_multicast already kfree_skb'd */ | 664 | /* nlmsg_multicast already kfree_skb'd */ |
665 | goto send_vendor_fail; | 665 | goto send_vendor_fail; |
666 | 666 | ||
667 | return 0; | 667 | return 0; |
668 | 668 | ||
669 | send_vendor_fail_skb: | 669 | send_vendor_fail_skb: |
670 | kfree_skb(skb); | 670 | kfree_skb(skb); |
671 | send_vendor_fail: | 671 | send_vendor_fail: |
672 | printk(KERN_WARNING | 672 | printk(KERN_WARNING |
673 | "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", | 673 | "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", |
674 | __func__, host_no, err); | 674 | __func__, host_no, err); |
675 | return err; | 675 | return err; |
676 | } | 676 | } |
677 | EXPORT_SYMBOL(scsi_nl_send_vendor_msg); | 677 | EXPORT_SYMBOL(scsi_nl_send_vendor_msg); |
678 | 678 | ||
679 | 679 | ||
680 | 680 |
include/linux/security.h
1 | /* | 1 | /* |
2 | * Linux Security plug | 2 | * Linux Security plug |
3 | * | 3 | * |
4 | * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> | 4 | * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> |
5 | * Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com> | 5 | * Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com> |
6 | * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> | 6 | * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> |
7 | * Copyright (C) 2001 James Morris <jmorris@intercode.com.au> | 7 | * Copyright (C) 2001 James Morris <jmorris@intercode.com.au> |
8 | * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group) | 8 | * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group) |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * Due to this file being licensed under the GPL there is controversy over | 15 | * Due to this file being licensed under the GPL there is controversy over |
16 | * whether this permits you to write a module that #includes this file | 16 | * whether this permits you to write a module that #includes this file |
17 | * without placing your module under the GPL. Please consult a lawyer for | 17 | * without placing your module under the GPL. Please consult a lawyer for |
18 | * advice before doing this. | 18 | * advice before doing this. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef __LINUX_SECURITY_H | 22 | #ifndef __LINUX_SECURITY_H |
23 | #define __LINUX_SECURITY_H | 23 | #define __LINUX_SECURITY_H |
24 | 24 | ||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/fsnotify.h> | 26 | #include <linux/fsnotify.h> |
27 | #include <linux/binfmts.h> | 27 | #include <linux/binfmts.h> |
28 | #include <linux/dcache.h> | 28 | #include <linux/dcache.h> |
29 | #include <linux/signal.h> | 29 | #include <linux/signal.h> |
30 | #include <linux/resource.h> | 30 | #include <linux/resource.h> |
31 | #include <linux/sem.h> | 31 | #include <linux/sem.h> |
32 | #include <linux/shm.h> | 32 | #include <linux/shm.h> |
33 | #include <linux/mm.h> /* PAGE_ALIGN */ | 33 | #include <linux/mm.h> /* PAGE_ALIGN */ |
34 | #include <linux/msg.h> | 34 | #include <linux/msg.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/key.h> | 36 | #include <linux/key.h> |
37 | #include <linux/xfrm.h> | 37 | #include <linux/xfrm.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <net/flow.h> | 39 | #include <net/flow.h> |
40 | 40 | ||
41 | /* Maximum number of letters for an LSM name string */ | 41 | /* Maximum number of letters for an LSM name string */ |
42 | #define SECURITY_NAME_MAX 10 | 42 | #define SECURITY_NAME_MAX 10 |
43 | 43 | ||
44 | /* If capable should audit the security request */ | 44 | /* If capable should audit the security request */ |
45 | #define SECURITY_CAP_NOAUDIT 0 | 45 | #define SECURITY_CAP_NOAUDIT 0 |
46 | #define SECURITY_CAP_AUDIT 1 | 46 | #define SECURITY_CAP_AUDIT 1 |
47 | 47 | ||
48 | struct ctl_table; | 48 | struct ctl_table; |
49 | struct audit_krule; | 49 | struct audit_krule; |
50 | struct user_namespace; | 50 | struct user_namespace; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * These functions are in security/capability.c and are used | 53 | * These functions are in security/capability.c and are used |
54 | * as the default capabilities functions | 54 | * as the default capabilities functions |
55 | */ | 55 | */ |
56 | extern int cap_capable(const struct cred *cred, struct user_namespace *ns, | 56 | extern int cap_capable(const struct cred *cred, struct user_namespace *ns, |
57 | int cap, int audit); | 57 | int cap, int audit); |
58 | extern int cap_settime(const struct timespec *ts, const struct timezone *tz); | 58 | extern int cap_settime(const struct timespec *ts, const struct timezone *tz); |
59 | extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); | 59 | extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); |
60 | extern int cap_ptrace_traceme(struct task_struct *parent); | 60 | extern int cap_ptrace_traceme(struct task_struct *parent); |
61 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); | 61 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); |
62 | extern int cap_capset(struct cred *new, const struct cred *old, | 62 | extern int cap_capset(struct cred *new, const struct cred *old, |
63 | const kernel_cap_t *effective, | 63 | const kernel_cap_t *effective, |
64 | const kernel_cap_t *inheritable, | 64 | const kernel_cap_t *inheritable, |
65 | const kernel_cap_t *permitted); | 65 | const kernel_cap_t *permitted); |
66 | extern int cap_bprm_set_creds(struct linux_binprm *bprm); | 66 | extern int cap_bprm_set_creds(struct linux_binprm *bprm); |
67 | extern int cap_bprm_secureexec(struct linux_binprm *bprm); | 67 | extern int cap_bprm_secureexec(struct linux_binprm *bprm); |
68 | extern int cap_inode_setxattr(struct dentry *dentry, const char *name, | 68 | extern int cap_inode_setxattr(struct dentry *dentry, const char *name, |
69 | const void *value, size_t size, int flags); | 69 | const void *value, size_t size, int flags); |
70 | extern int cap_inode_removexattr(struct dentry *dentry, const char *name); | 70 | extern int cap_inode_removexattr(struct dentry *dentry, const char *name); |
71 | extern int cap_inode_need_killpriv(struct dentry *dentry); | 71 | extern int cap_inode_need_killpriv(struct dentry *dentry); |
72 | extern int cap_inode_killpriv(struct dentry *dentry); | 72 | extern int cap_inode_killpriv(struct dentry *dentry); |
73 | extern int cap_file_mmap(struct file *file, unsigned long reqprot, | 73 | extern int cap_file_mmap(struct file *file, unsigned long reqprot, |
74 | unsigned long prot, unsigned long flags, | 74 | unsigned long prot, unsigned long flags, |
75 | unsigned long addr, unsigned long addr_only); | 75 | unsigned long addr, unsigned long addr_only); |
76 | extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags); | 76 | extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags); |
77 | extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 77 | extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
78 | unsigned long arg4, unsigned long arg5); | 78 | unsigned long arg4, unsigned long arg5); |
79 | extern int cap_task_setscheduler(struct task_struct *p); | 79 | extern int cap_task_setscheduler(struct task_struct *p); |
80 | extern int cap_task_setioprio(struct task_struct *p, int ioprio); | 80 | extern int cap_task_setioprio(struct task_struct *p, int ioprio); |
81 | extern int cap_task_setnice(struct task_struct *p, int nice); | 81 | extern int cap_task_setnice(struct task_struct *p, int nice); |
82 | extern int cap_vm_enough_memory(struct mm_struct *mm, long pages); | 82 | extern int cap_vm_enough_memory(struct mm_struct *mm, long pages); |
83 | 83 | ||
84 | struct msghdr; | 84 | struct msghdr; |
85 | struct sk_buff; | 85 | struct sk_buff; |
86 | struct sock; | 86 | struct sock; |
87 | struct sockaddr; | 87 | struct sockaddr; |
88 | struct socket; | 88 | struct socket; |
89 | struct flowi; | 89 | struct flowi; |
90 | struct dst_entry; | 90 | struct dst_entry; |
91 | struct xfrm_selector; | 91 | struct xfrm_selector; |
92 | struct xfrm_policy; | 92 | struct xfrm_policy; |
93 | struct xfrm_state; | 93 | struct xfrm_state; |
94 | struct xfrm_user_sec_ctx; | 94 | struct xfrm_user_sec_ctx; |
95 | struct seq_file; | 95 | struct seq_file; |
96 | 96 | ||
97 | extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); | 97 | extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); |
98 | extern int cap_netlink_recv(struct sk_buff *skb, int cap); | ||
99 | 98 | ||
100 | void reset_security_ops(void); | 99 | void reset_security_ops(void); |
101 | 100 | ||
102 | #ifdef CONFIG_MMU | 101 | #ifdef CONFIG_MMU |
103 | extern unsigned long mmap_min_addr; | 102 | extern unsigned long mmap_min_addr; |
104 | extern unsigned long dac_mmap_min_addr; | 103 | extern unsigned long dac_mmap_min_addr; |
105 | #else | 104 | #else |
106 | #define dac_mmap_min_addr 0UL | 105 | #define dac_mmap_min_addr 0UL |
107 | #endif | 106 | #endif |
108 | 107 | ||
109 | /* | 108 | /* |
110 | * Values used in the task_security_ops calls | 109 | * Values used in the task_security_ops calls |
111 | */ | 110 | */ |
112 | /* setuid or setgid, id0 == uid or gid */ | 111 | /* setuid or setgid, id0 == uid or gid */ |
113 | #define LSM_SETID_ID 1 | 112 | #define LSM_SETID_ID 1 |
114 | 113 | ||
115 | /* setreuid or setregid, id0 == real, id1 == eff */ | 114 | /* setreuid or setregid, id0 == real, id1 == eff */ |
116 | #define LSM_SETID_RE 2 | 115 | #define LSM_SETID_RE 2 |
117 | 116 | ||
118 | /* setresuid or setresgid, id0 == real, id1 == eff, uid2 == saved */ | 117 | /* setresuid or setresgid, id0 == real, id1 == eff, uid2 == saved */ |
119 | #define LSM_SETID_RES 4 | 118 | #define LSM_SETID_RES 4 |
120 | 119 | ||
121 | /* setfsuid or setfsgid, id0 == fsuid or fsgid */ | 120 | /* setfsuid or setfsgid, id0 == fsuid or fsgid */ |
122 | #define LSM_SETID_FS 8 | 121 | #define LSM_SETID_FS 8 |
123 | 122 | ||
124 | /* forward declares to avoid warnings */ | 123 | /* forward declares to avoid warnings */ |
125 | struct sched_param; | 124 | struct sched_param; |
126 | struct request_sock; | 125 | struct request_sock; |
127 | 126 | ||
128 | /* bprm->unsafe reasons */ | 127 | /* bprm->unsafe reasons */ |
129 | #define LSM_UNSAFE_SHARE 1 | 128 | #define LSM_UNSAFE_SHARE 1 |
130 | #define LSM_UNSAFE_PTRACE 2 | 129 | #define LSM_UNSAFE_PTRACE 2 |
131 | #define LSM_UNSAFE_PTRACE_CAP 4 | 130 | #define LSM_UNSAFE_PTRACE_CAP 4 |
132 | 131 | ||
133 | #ifdef CONFIG_MMU | 132 | #ifdef CONFIG_MMU |
134 | /* | 133 | /* |
135 | * If a hint addr is less than mmap_min_addr change hint to be as | 134 | * If a hint addr is less than mmap_min_addr change hint to be as |
136 | * low as possible but still greater than mmap_min_addr | 135 | * low as possible but still greater than mmap_min_addr |
137 | */ | 136 | */ |
138 | static inline unsigned long round_hint_to_min(unsigned long hint) | 137 | static inline unsigned long round_hint_to_min(unsigned long hint) |
139 | { | 138 | { |
140 | hint &= PAGE_MASK; | 139 | hint &= PAGE_MASK; |
141 | if (((void *)hint != NULL) && | 140 | if (((void *)hint != NULL) && |
142 | (hint < mmap_min_addr)) | 141 | (hint < mmap_min_addr)) |
143 | return PAGE_ALIGN(mmap_min_addr); | 142 | return PAGE_ALIGN(mmap_min_addr); |
144 | return hint; | 143 | return hint; |
145 | } | 144 | } |
146 | extern int mmap_min_addr_handler(struct ctl_table *table, int write, | 145 | extern int mmap_min_addr_handler(struct ctl_table *table, int write, |
147 | void __user *buffer, size_t *lenp, loff_t *ppos); | 146 | void __user *buffer, size_t *lenp, loff_t *ppos); |
148 | #endif | 147 | #endif |
149 | 148 | ||
150 | #ifdef CONFIG_SECURITY | 149 | #ifdef CONFIG_SECURITY |
151 | 150 | ||
152 | struct security_mnt_opts { | 151 | struct security_mnt_opts { |
153 | char **mnt_opts; | 152 | char **mnt_opts; |
154 | int *mnt_opts_flags; | 153 | int *mnt_opts_flags; |
155 | int num_mnt_opts; | 154 | int num_mnt_opts; |
156 | }; | 155 | }; |
157 | 156 | ||
158 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) | 157 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) |
159 | { | 158 | { |
160 | opts->mnt_opts = NULL; | 159 | opts->mnt_opts = NULL; |
161 | opts->mnt_opts_flags = NULL; | 160 | opts->mnt_opts_flags = NULL; |
162 | opts->num_mnt_opts = 0; | 161 | opts->num_mnt_opts = 0; |
163 | } | 162 | } |
164 | 163 | ||
165 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | 164 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) |
166 | { | 165 | { |
167 | int i; | 166 | int i; |
168 | if (opts->mnt_opts) | 167 | if (opts->mnt_opts) |
169 | for (i = 0; i < opts->num_mnt_opts; i++) | 168 | for (i = 0; i < opts->num_mnt_opts; i++) |
170 | kfree(opts->mnt_opts[i]); | 169 | kfree(opts->mnt_opts[i]); |
171 | kfree(opts->mnt_opts); | 170 | kfree(opts->mnt_opts); |
172 | opts->mnt_opts = NULL; | 171 | opts->mnt_opts = NULL; |
173 | kfree(opts->mnt_opts_flags); | 172 | kfree(opts->mnt_opts_flags); |
174 | opts->mnt_opts_flags = NULL; | 173 | opts->mnt_opts_flags = NULL; |
175 | opts->num_mnt_opts = 0; | 174 | opts->num_mnt_opts = 0; |
176 | } | 175 | } |
177 | 176 | ||
178 | /** | 177 | /** |
179 | * struct security_operations - main security structure | 178 | * struct security_operations - main security structure |
180 | * | 179 | * |
181 | * Security module identifier. | 180 | * Security module identifier. |
182 | * | 181 | * |
183 | * @name: | 182 | * @name: |
184 | * A string that acts as a unique identifeir for the LSM with max number | 183 | * A string that acts as a unique identifeir for the LSM with max number |
185 | * of characters = SECURITY_NAME_MAX. | 184 | * of characters = SECURITY_NAME_MAX. |
186 | * | 185 | * |
187 | * Security hooks for program execution operations. | 186 | * Security hooks for program execution operations. |
188 | * | 187 | * |
189 | * @bprm_set_creds: | 188 | * @bprm_set_creds: |
190 | * Save security information in the bprm->security field, typically based | 189 | * Save security information in the bprm->security field, typically based |
191 | * on information about the bprm->file, for later use by the apply_creds | 190 | * on information about the bprm->file, for later use by the apply_creds |
192 | * hook. This hook may also optionally check permissions (e.g. for | 191 | * hook. This hook may also optionally check permissions (e.g. for |
193 | * transitions between security domains). | 192 | * transitions between security domains). |
194 | * This hook may be called multiple times during a single execve, e.g. for | 193 | * This hook may be called multiple times during a single execve, e.g. for |
195 | * interpreters. The hook can tell whether it has already been called by | 194 | * interpreters. The hook can tell whether it has already been called by |
196 | * checking to see if @bprm->security is non-NULL. If so, then the hook | 195 | * checking to see if @bprm->security is non-NULL. If so, then the hook |
197 | * may decide either to retain the security information saved earlier or | 196 | * may decide either to retain the security information saved earlier or |
198 | * to replace it. | 197 | * to replace it. |
199 | * @bprm contains the linux_binprm structure. | 198 | * @bprm contains the linux_binprm structure. |
200 | * Return 0 if the hook is successful and permission is granted. | 199 | * Return 0 if the hook is successful and permission is granted. |
201 | * @bprm_check_security: | 200 | * @bprm_check_security: |
202 | * This hook mediates the point when a search for a binary handler will | 201 | * This hook mediates the point when a search for a binary handler will |
203 | * begin. It allows a check the @bprm->security value which is set in the | 202 | * begin. It allows a check the @bprm->security value which is set in the |
204 | * preceding set_creds call. The primary difference from set_creds is | 203 | * preceding set_creds call. The primary difference from set_creds is |
205 | * that the argv list and envp list are reliably available in @bprm. This | 204 | * that the argv list and envp list are reliably available in @bprm. This |
206 | * hook may be called multiple times during a single execve; and in each | 205 | * hook may be called multiple times during a single execve; and in each |
207 | * pass set_creds is called first. | 206 | * pass set_creds is called first. |
208 | * @bprm contains the linux_binprm structure. | 207 | * @bprm contains the linux_binprm structure. |
209 | * Return 0 if the hook is successful and permission is granted. | 208 | * Return 0 if the hook is successful and permission is granted. |
210 | * @bprm_committing_creds: | 209 | * @bprm_committing_creds: |
211 | * Prepare to install the new security attributes of a process being | 210 | * Prepare to install the new security attributes of a process being |
212 | * transformed by an execve operation, based on the old credentials | 211 | * transformed by an execve operation, based on the old credentials |
213 | * pointed to by @current->cred and the information set in @bprm->cred by | 212 | * pointed to by @current->cred and the information set in @bprm->cred by |
214 | * the bprm_set_creds hook. @bprm points to the linux_binprm structure. | 213 | * the bprm_set_creds hook. @bprm points to the linux_binprm structure. |
215 | * This hook is a good place to perform state changes on the process such | 214 | * This hook is a good place to perform state changes on the process such |
216 | * as closing open file descriptors to which access will no longer be | 215 | * as closing open file descriptors to which access will no longer be |
217 | * granted when the attributes are changed. This is called immediately | 216 | * granted when the attributes are changed. This is called immediately |
218 | * before commit_creds(). | 217 | * before commit_creds(). |
219 | * @bprm_committed_creds: | 218 | * @bprm_committed_creds: |
220 | * Tidy up after the installation of the new security attributes of a | 219 | * Tidy up after the installation of the new security attributes of a |
221 | * process being transformed by an execve operation. The new credentials | 220 | * process being transformed by an execve operation. The new credentials |
222 | * have, by this point, been set to @current->cred. @bprm points to the | 221 | * have, by this point, been set to @current->cred. @bprm points to the |
223 | * linux_binprm structure. This hook is a good place to perform state | 222 | * linux_binprm structure. This hook is a good place to perform state |
224 | * changes on the process such as clearing out non-inheritable signal | 223 | * changes on the process such as clearing out non-inheritable signal |
225 | * state. This is called immediately after commit_creds(). | 224 | * state. This is called immediately after commit_creds(). |
226 | * @bprm_secureexec: | 225 | * @bprm_secureexec: |
227 | * Return a boolean value (0 or 1) indicating whether a "secure exec" | 226 | * Return a boolean value (0 or 1) indicating whether a "secure exec" |
228 | * is required. The flag is passed in the auxiliary table | 227 | * is required. The flag is passed in the auxiliary table |
229 | * on the initial stack to the ELF interpreter to indicate whether libc | 228 | * on the initial stack to the ELF interpreter to indicate whether libc |
230 | * should enable secure mode. | 229 | * should enable secure mode. |
231 | * @bprm contains the linux_binprm structure. | 230 | * @bprm contains the linux_binprm structure. |
232 | * | 231 | * |
233 | * Security hooks for filesystem operations. | 232 | * Security hooks for filesystem operations. |
234 | * | 233 | * |
235 | * @sb_alloc_security: | 234 | * @sb_alloc_security: |
236 | * Allocate and attach a security structure to the sb->s_security field. | 235 | * Allocate and attach a security structure to the sb->s_security field. |
237 | * The s_security field is initialized to NULL when the structure is | 236 | * The s_security field is initialized to NULL when the structure is |
238 | * allocated. | 237 | * allocated. |
239 | * @sb contains the super_block structure to be modified. | 238 | * @sb contains the super_block structure to be modified. |
240 | * Return 0 if operation was successful. | 239 | * Return 0 if operation was successful. |
241 | * @sb_free_security: | 240 | * @sb_free_security: |
242 | * Deallocate and clear the sb->s_security field. | 241 | * Deallocate and clear the sb->s_security field. |
243 | * @sb contains the super_block structure to be modified. | 242 | * @sb contains the super_block structure to be modified. |
244 | * @sb_statfs: | 243 | * @sb_statfs: |
245 | * Check permission before obtaining filesystem statistics for the @mnt | 244 | * Check permission before obtaining filesystem statistics for the @mnt |
246 | * mountpoint. | 245 | * mountpoint. |
247 | * @dentry is a handle on the superblock for the filesystem. | 246 | * @dentry is a handle on the superblock for the filesystem. |
248 | * Return 0 if permission is granted. | 247 | * Return 0 if permission is granted. |
249 | * @sb_mount: | 248 | * @sb_mount: |
250 | * Check permission before an object specified by @dev_name is mounted on | 249 | * Check permission before an object specified by @dev_name is mounted on |
251 | * the mount point named by @nd. For an ordinary mount, @dev_name | 250 | * the mount point named by @nd. For an ordinary mount, @dev_name |
252 | * identifies a device if the file system type requires a device. For a | 251 | * identifies a device if the file system type requires a device. For a |
253 | * remount (@flags & MS_REMOUNT), @dev_name is irrelevant. For a | 252 | * remount (@flags & MS_REMOUNT), @dev_name is irrelevant. For a |
254 | * loopback/bind mount (@flags & MS_BIND), @dev_name identifies the | 253 | * loopback/bind mount (@flags & MS_BIND), @dev_name identifies the |
255 | * pathname of the object being mounted. | 254 | * pathname of the object being mounted. |
256 | * @dev_name contains the name for object being mounted. | 255 | * @dev_name contains the name for object being mounted. |
257 | * @path contains the path for mount point object. | 256 | * @path contains the path for mount point object. |
258 | * @type contains the filesystem type. | 257 | * @type contains the filesystem type. |
259 | * @flags contains the mount flags. | 258 | * @flags contains the mount flags. |
260 | * @data contains the filesystem-specific data. | 259 | * @data contains the filesystem-specific data. |
261 | * Return 0 if permission is granted. | 260 | * Return 0 if permission is granted. |
262 | * @sb_copy_data: | 261 | * @sb_copy_data: |
263 | * Allow mount option data to be copied prior to parsing by the filesystem, | 262 | * Allow mount option data to be copied prior to parsing by the filesystem, |
264 | * so that the security module can extract security-specific mount | 263 | * so that the security module can extract security-specific mount |
265 | * options cleanly (a filesystem may modify the data e.g. with strsep()). | 264 | * options cleanly (a filesystem may modify the data e.g. with strsep()). |
266 | * This also allows the original mount data to be stripped of security- | 265 | * This also allows the original mount data to be stripped of security- |
267 | * specific options to avoid having to make filesystems aware of them. | 266 | * specific options to avoid having to make filesystems aware of them. |
268 | * @type the type of filesystem being mounted. | 267 | * @type the type of filesystem being mounted. |
269 | * @orig the original mount data copied from userspace. | 268 | * @orig the original mount data copied from userspace. |
270 | * @copy copied data which will be passed to the security module. | 269 | * @copy copied data which will be passed to the security module. |
271 | * Returns 0 if the copy was successful. | 270 | * Returns 0 if the copy was successful. |
272 | * @sb_remount: | 271 | * @sb_remount: |
273 | * Extracts security system specifc mount options and verifys no changes | 272 | * Extracts security system specifc mount options and verifys no changes |
274 | * are being made to those options. | 273 | * are being made to those options. |
275 | * @sb superblock being remounted | 274 | * @sb superblock being remounted |
276 | * @data contains the filesystem-specific data. | 275 | * @data contains the filesystem-specific data. |
277 | * Return 0 if permission is granted. | 276 | * Return 0 if permission is granted. |
278 | * @sb_umount: | 277 | * @sb_umount: |
279 | * Check permission before the @mnt file system is unmounted. | 278 | * Check permission before the @mnt file system is unmounted. |
280 | * @mnt contains the mounted file system. | 279 | * @mnt contains the mounted file system. |
281 | * @flags contains the unmount flags, e.g. MNT_FORCE. | 280 | * @flags contains the unmount flags, e.g. MNT_FORCE. |
282 | * Return 0 if permission is granted. | 281 | * Return 0 if permission is granted. |
283 | * @sb_pivotroot: | 282 | * @sb_pivotroot: |
284 | * Check permission before pivoting the root filesystem. | 283 | * Check permission before pivoting the root filesystem. |
285 | * @old_path contains the path for the new location of the current root (put_old). | 284 | * @old_path contains the path for the new location of the current root (put_old). |
286 | * @new_path contains the path for the new root (new_root). | 285 | * @new_path contains the path for the new root (new_root). |
287 | * Return 0 if permission is granted. | 286 | * Return 0 if permission is granted. |
288 | * @sb_set_mnt_opts: | 287 | * @sb_set_mnt_opts: |
289 | * Set the security relevant mount options used for a superblock | 288 | * Set the security relevant mount options used for a superblock |
290 | * @sb the superblock to set security mount options for | 289 | * @sb the superblock to set security mount options for |
291 | * @opts binary data structure containing all lsm mount data | 290 | * @opts binary data structure containing all lsm mount data |
292 | * @sb_clone_mnt_opts: | 291 | * @sb_clone_mnt_opts: |
293 | * Copy all security options from a given superblock to another | 292 | * Copy all security options from a given superblock to another |
294 | * @oldsb old superblock which contain information to clone | 293 | * @oldsb old superblock which contain information to clone |
295 | * @newsb new superblock which needs filled in | 294 | * @newsb new superblock which needs filled in |
296 | * @sb_parse_opts_str: | 295 | * @sb_parse_opts_str: |
297 | * Parse a string of security data filling in the opts structure | 296 | * Parse a string of security data filling in the opts structure |
298 | * @options string containing all mount options known by the LSM | 297 | * @options string containing all mount options known by the LSM |
299 | * @opts binary data structure usable by the LSM | 298 | * @opts binary data structure usable by the LSM |
300 | * | 299 | * |
301 | * Security hooks for inode operations. | 300 | * Security hooks for inode operations. |
302 | * | 301 | * |
303 | * @inode_alloc_security: | 302 | * @inode_alloc_security: |
304 | * Allocate and attach a security structure to @inode->i_security. The | 303 | * Allocate and attach a security structure to @inode->i_security. The |
305 | * i_security field is initialized to NULL when the inode structure is | 304 | * i_security field is initialized to NULL when the inode structure is |
306 | * allocated. | 305 | * allocated. |
307 | * @inode contains the inode structure. | 306 | * @inode contains the inode structure. |
308 | * Return 0 if operation was successful. | 307 | * Return 0 if operation was successful. |
309 | * @inode_free_security: | 308 | * @inode_free_security: |
310 | * @inode contains the inode structure. | 309 | * @inode contains the inode structure. |
311 | * Deallocate the inode security structure and set @inode->i_security to | 310 | * Deallocate the inode security structure and set @inode->i_security to |
312 | * NULL. | 311 | * NULL. |
313 | * @inode_init_security: | 312 | * @inode_init_security: |
314 | * Obtain the security attribute name suffix and value to set on a newly | 313 | * Obtain the security attribute name suffix and value to set on a newly |
315 | * created inode and set up the incore security field for the new inode. | 314 | * created inode and set up the incore security field for the new inode. |
316 | * This hook is called by the fs code as part of the inode creation | 315 | * This hook is called by the fs code as part of the inode creation |
317 | * transaction and provides for atomic labeling of the inode, unlike | 316 | * transaction and provides for atomic labeling of the inode, unlike |
318 | * the post_create/mkdir/... hooks called by the VFS. The hook function | 317 | * the post_create/mkdir/... hooks called by the VFS. The hook function |
319 | * is expected to allocate the name and value via kmalloc, with the caller | 318 | * is expected to allocate the name and value via kmalloc, with the caller |
320 | * being responsible for calling kfree after using them. | 319 | * being responsible for calling kfree after using them. |
321 | * If the security module does not use security attributes or does | 320 | * If the security module does not use security attributes or does |
322 | * not wish to put a security attribute on this particular inode, | 321 | * not wish to put a security attribute on this particular inode, |
323 | * then it should return -EOPNOTSUPP to skip this processing. | 322 | * then it should return -EOPNOTSUPP to skip this processing. |
324 | * @inode contains the inode structure of the newly created inode. | 323 | * @inode contains the inode structure of the newly created inode. |
325 | * @dir contains the inode structure of the parent directory. | 324 | * @dir contains the inode structure of the parent directory. |
326 | * @qstr contains the last path component of the new object | 325 | * @qstr contains the last path component of the new object |
327 | * @name will be set to the allocated name suffix (e.g. selinux). | 326 | * @name will be set to the allocated name suffix (e.g. selinux). |
328 | * @value will be set to the allocated attribute value. | 327 | * @value will be set to the allocated attribute value. |
329 | * @len will be set to the length of the value. | 328 | * @len will be set to the length of the value. |
330 | * Returns 0 if @name and @value have been successfully set, | 329 | * Returns 0 if @name and @value have been successfully set, |
331 | * -EOPNOTSUPP if no security attribute is needed, or | 330 | * -EOPNOTSUPP if no security attribute is needed, or |
332 | * -ENOMEM on memory allocation failure. | 331 | * -ENOMEM on memory allocation failure. |
333 | * @inode_create: | 332 | * @inode_create: |
334 | * Check permission to create a regular file. | 333 | * Check permission to create a regular file. |
335 | * @dir contains inode structure of the parent of the new file. | 334 | * @dir contains inode structure of the parent of the new file. |
336 | * @dentry contains the dentry structure for the file to be created. | 335 | * @dentry contains the dentry structure for the file to be created. |
337 | * @mode contains the file mode of the file to be created. | 336 | * @mode contains the file mode of the file to be created. |
338 | * Return 0 if permission is granted. | 337 | * Return 0 if permission is granted. |
339 | * @inode_link: | 338 | * @inode_link: |
340 | * Check permission before creating a new hard link to a file. | 339 | * Check permission before creating a new hard link to a file. |
341 | * @old_dentry contains the dentry structure for an existing link to the file. | 340 | * @old_dentry contains the dentry structure for an existing link to the file. |
342 | * @dir contains the inode structure of the parent directory of the new link. | 341 | * @dir contains the inode structure of the parent directory of the new link. |
343 | * @new_dentry contains the dentry structure for the new link. | 342 | * @new_dentry contains the dentry structure for the new link. |
344 | * Return 0 if permission is granted. | 343 | * Return 0 if permission is granted. |
345 | * @path_link: | 344 | * @path_link: |
346 | * Check permission before creating a new hard link to a file. | 345 | * Check permission before creating a new hard link to a file. |
347 | * @old_dentry contains the dentry structure for an existing link | 346 | * @old_dentry contains the dentry structure for an existing link |
348 | * to the file. | 347 | * to the file. |
349 | * @new_dir contains the path structure of the parent directory of | 348 | * @new_dir contains the path structure of the parent directory of |
350 | * the new link. | 349 | * the new link. |
351 | * @new_dentry contains the dentry structure for the new link. | 350 | * @new_dentry contains the dentry structure for the new link. |
352 | * Return 0 if permission is granted. | 351 | * Return 0 if permission is granted. |
353 | * @inode_unlink: | 352 | * @inode_unlink: |
354 | * Check the permission to remove a hard link to a file. | 353 | * Check the permission to remove a hard link to a file. |
355 | * @dir contains the inode structure of parent directory of the file. | 354 | * @dir contains the inode structure of parent directory of the file. |
356 | * @dentry contains the dentry structure for file to be unlinked. | 355 | * @dentry contains the dentry structure for file to be unlinked. |
357 | * Return 0 if permission is granted. | 356 | * Return 0 if permission is granted. |
358 | * @path_unlink: | 357 | * @path_unlink: |
359 | * Check the permission to remove a hard link to a file. | 358 | * Check the permission to remove a hard link to a file. |
360 | * @dir contains the path structure of parent directory of the file. | 359 | * @dir contains the path structure of parent directory of the file. |
361 | * @dentry contains the dentry structure for file to be unlinked. | 360 | * @dentry contains the dentry structure for file to be unlinked. |
362 | * Return 0 if permission is granted. | 361 | * Return 0 if permission is granted. |
363 | * @inode_symlink: | 362 | * @inode_symlink: |
364 | * Check the permission to create a symbolic link to a file. | 363 | * Check the permission to create a symbolic link to a file. |
365 | * @dir contains the inode structure of parent directory of the symbolic link. | 364 | * @dir contains the inode structure of parent directory of the symbolic link. |
366 | * @dentry contains the dentry structure of the symbolic link. | 365 | * @dentry contains the dentry structure of the symbolic link. |
367 | * @old_name contains the pathname of file. | 366 | * @old_name contains the pathname of file. |
368 | * Return 0 if permission is granted. | 367 | * Return 0 if permission is granted. |
369 | * @path_symlink: | 368 | * @path_symlink: |
370 | * Check the permission to create a symbolic link to a file. | 369 | * Check the permission to create a symbolic link to a file. |
371 | * @dir contains the path structure of parent directory of | 370 | * @dir contains the path structure of parent directory of |
372 | * the symbolic link. | 371 | * the symbolic link. |
373 | * @dentry contains the dentry structure of the symbolic link. | 372 | * @dentry contains the dentry structure of the symbolic link. |
374 | * @old_name contains the pathname of file. | 373 | * @old_name contains the pathname of file. |
375 | * Return 0 if permission is granted. | 374 | * Return 0 if permission is granted. |
376 | * @inode_mkdir: | 375 | * @inode_mkdir: |
377 | * Check permissions to create a new directory in the existing directory | 376 | * Check permissions to create a new directory in the existing directory |
378 | * associated with inode strcture @dir. | 377 | * associated with inode strcture @dir. |
379 | * @dir containst the inode structure of parent of the directory to be created. | 378 | * @dir containst the inode structure of parent of the directory to be created. |
380 | * @dentry contains the dentry structure of new directory. | 379 | * @dentry contains the dentry structure of new directory. |
381 | * @mode contains the mode of new directory. | 380 | * @mode contains the mode of new directory. |
382 | * Return 0 if permission is granted. | 381 | * Return 0 if permission is granted. |
383 | * @path_mkdir: | 382 | * @path_mkdir: |
384 | * Check permissions to create a new directory in the existing directory | 383 | * Check permissions to create a new directory in the existing directory |
385 | * associated with path strcture @path. | 384 | * associated with path strcture @path. |
386 | * @dir containst the path structure of parent of the directory | 385 | * @dir containst the path structure of parent of the directory |
387 | * to be created. | 386 | * to be created. |
388 | * @dentry contains the dentry structure of new directory. | 387 | * @dentry contains the dentry structure of new directory. |
389 | * @mode contains the mode of new directory. | 388 | * @mode contains the mode of new directory. |
390 | * Return 0 if permission is granted. | 389 | * Return 0 if permission is granted. |
391 | * @inode_rmdir: | 390 | * @inode_rmdir: |
392 | * Check the permission to remove a directory. | 391 | * Check the permission to remove a directory. |
393 | * @dir contains the inode structure of parent of the directory to be removed. | 392 | * @dir contains the inode structure of parent of the directory to be removed. |
394 | * @dentry contains the dentry structure of directory to be removed. | 393 | * @dentry contains the dentry structure of directory to be removed. |
395 | * Return 0 if permission is granted. | 394 | * Return 0 if permission is granted. |
396 | * @path_rmdir: | 395 | * @path_rmdir: |
397 | * Check the permission to remove a directory. | 396 | * Check the permission to remove a directory. |
398 | * @dir contains the path structure of parent of the directory to be | 397 | * @dir contains the path structure of parent of the directory to be |
399 | * removed. | 398 | * removed. |
400 | * @dentry contains the dentry structure of directory to be removed. | 399 | * @dentry contains the dentry structure of directory to be removed. |
401 | * Return 0 if permission is granted. | 400 | * Return 0 if permission is granted. |
402 | * @inode_mknod: | 401 | * @inode_mknod: |
403 | * Check permissions when creating a special file (or a socket or a fifo | 402 | * Check permissions when creating a special file (or a socket or a fifo |
404 | * file created via the mknod system call). Note that if mknod operation | 403 | * file created via the mknod system call). Note that if mknod operation |
405 | * is being done for a regular file, then the create hook will be called | 404 | * is being done for a regular file, then the create hook will be called |
406 | * and not this hook. | 405 | * and not this hook. |
407 | * @dir contains the inode structure of parent of the new file. | 406 | * @dir contains the inode structure of parent of the new file. |
408 | * @dentry contains the dentry structure of the new file. | 407 | * @dentry contains the dentry structure of the new file. |
409 | * @mode contains the mode of the new file. | 408 | * @mode contains the mode of the new file. |
410 | * @dev contains the device number. | 409 | * @dev contains the device number. |
411 | * Return 0 if permission is granted. | 410 | * Return 0 if permission is granted. |
412 | * @path_mknod: | 411 | * @path_mknod: |
413 | * Check permissions when creating a file. Note that this hook is called | 412 | * Check permissions when creating a file. Note that this hook is called |
414 | * even if mknod operation is being done for a regular file. | 413 | * even if mknod operation is being done for a regular file. |
415 | * @dir contains the path structure of parent of the new file. | 414 | * @dir contains the path structure of parent of the new file. |
416 | * @dentry contains the dentry structure of the new file. | 415 | * @dentry contains the dentry structure of the new file. |
417 | * @mode contains the mode of the new file. | 416 | * @mode contains the mode of the new file. |
418 | * @dev contains the undecoded device number. Use new_decode_dev() to get | 417 | * @dev contains the undecoded device number. Use new_decode_dev() to get |
419 | * the decoded device number. | 418 | * the decoded device number. |
420 | * Return 0 if permission is granted. | 419 | * Return 0 if permission is granted. |
421 | * @inode_rename: | 420 | * @inode_rename: |
422 | * Check for permission to rename a file or directory. | 421 | * Check for permission to rename a file or directory. |
423 | * @old_dir contains the inode structure for parent of the old link. | 422 | * @old_dir contains the inode structure for parent of the old link. |
424 | * @old_dentry contains the dentry structure of the old link. | 423 | * @old_dentry contains the dentry structure of the old link. |
425 | * @new_dir contains the inode structure for parent of the new link. | 424 | * @new_dir contains the inode structure for parent of the new link. |
426 | * @new_dentry contains the dentry structure of the new link. | 425 | * @new_dentry contains the dentry structure of the new link. |
427 | * Return 0 if permission is granted. | 426 | * Return 0 if permission is granted. |
428 | * @path_rename: | 427 | * @path_rename: |
429 | * Check for permission to rename a file or directory. | 428 | * Check for permission to rename a file or directory. |
430 | * @old_dir contains the path structure for parent of the old link. | 429 | * @old_dir contains the path structure for parent of the old link. |
431 | * @old_dentry contains the dentry structure of the old link. | 430 | * @old_dentry contains the dentry structure of the old link. |
432 | * @new_dir contains the path structure for parent of the new link. | 431 | * @new_dir contains the path structure for parent of the new link. |
433 | * @new_dentry contains the dentry structure of the new link. | 432 | * @new_dentry contains the dentry structure of the new link. |
434 | * Return 0 if permission is granted. | 433 | * Return 0 if permission is granted. |
435 | * @path_chmod: | 434 | * @path_chmod: |
436 | * Check for permission to change DAC's permission of a file or directory. | 435 | * Check for permission to change DAC's permission of a file or directory. |
437 | * @dentry contains the dentry structure. | 436 | * @dentry contains the dentry structure. |
438 | * @mnt contains the vfsmnt structure. | 437 | * @mnt contains the vfsmnt structure. |
439 | * @mode contains DAC's mode. | 438 | * @mode contains DAC's mode. |
440 | * Return 0 if permission is granted. | 439 | * Return 0 if permission is granted. |
441 | * @path_chown: | 440 | * @path_chown: |
442 | * Check for permission to change owner/group of a file or directory. | 441 | * Check for permission to change owner/group of a file or directory. |
443 | * @path contains the path structure. | 442 | * @path contains the path structure. |
444 | * @uid contains new owner's ID. | 443 | * @uid contains new owner's ID. |
445 | * @gid contains new group's ID. | 444 | * @gid contains new group's ID. |
446 | * Return 0 if permission is granted. | 445 | * Return 0 if permission is granted. |
447 | * @path_chroot: | 446 | * @path_chroot: |
448 | * Check for permission to change root directory. | 447 | * Check for permission to change root directory. |
449 | * @path contains the path structure. | 448 | * @path contains the path structure. |
450 | * Return 0 if permission is granted. | 449 | * Return 0 if permission is granted. |
451 | * @inode_readlink: | 450 | * @inode_readlink: |
452 | * Check the permission to read the symbolic link. | 451 | * Check the permission to read the symbolic link. |
453 | * @dentry contains the dentry structure for the file link. | 452 | * @dentry contains the dentry structure for the file link. |
454 | * Return 0 if permission is granted. | 453 | * Return 0 if permission is granted. |
455 | * @inode_follow_link: | 454 | * @inode_follow_link: |
456 | * Check permission to follow a symbolic link when looking up a pathname. | 455 | * Check permission to follow a symbolic link when looking up a pathname. |
457 | * @dentry contains the dentry structure for the link. | 456 | * @dentry contains the dentry structure for the link. |
458 | * @nd contains the nameidata structure for the parent directory. | 457 | * @nd contains the nameidata structure for the parent directory. |
459 | * Return 0 if permission is granted. | 458 | * Return 0 if permission is granted. |
460 | * @inode_permission: | 459 | * @inode_permission: |
461 | * Check permission before accessing an inode. This hook is called by the | 460 | * Check permission before accessing an inode. This hook is called by the |
462 | * existing Linux permission function, so a security module can use it to | 461 | * existing Linux permission function, so a security module can use it to |
463 | * provide additional checking for existing Linux permission checks. | 462 | * provide additional checking for existing Linux permission checks. |
464 | * Notice that this hook is called when a file is opened (as well as many | 463 | * Notice that this hook is called when a file is opened (as well as many |
465 | * other operations), whereas the file_security_ops permission hook is | 464 | * other operations), whereas the file_security_ops permission hook is |
466 | * called when the actual read/write operations are performed. | 465 | * called when the actual read/write operations are performed. |
467 | * @inode contains the inode structure to check. | 466 | * @inode contains the inode structure to check. |
468 | * @mask contains the permission mask. | 467 | * @mask contains the permission mask. |
469 | * Return 0 if permission is granted. | 468 | * Return 0 if permission is granted. |
470 | * @inode_setattr: | 469 | * @inode_setattr: |
471 | * Check permission before setting file attributes. Note that the kernel | 470 | * Check permission before setting file attributes. Note that the kernel |
472 | * call to notify_change is performed from several locations, whenever | 471 | * call to notify_change is performed from several locations, whenever |
473 | * file attributes change (such as when a file is truncated, chown/chmod | 472 | * file attributes change (such as when a file is truncated, chown/chmod |
474 | * operations, transferring disk quotas, etc). | 473 | * operations, transferring disk quotas, etc). |
475 | * @dentry contains the dentry structure for the file. | 474 | * @dentry contains the dentry structure for the file. |
476 | * @attr is the iattr structure containing the new file attributes. | 475 | * @attr is the iattr structure containing the new file attributes. |
477 | * Return 0 if permission is granted. | 476 | * Return 0 if permission is granted. |
478 | * @path_truncate: | 477 | * @path_truncate: |
479 | * Check permission before truncating a file. | 478 | * Check permission before truncating a file. |
480 | * @path contains the path structure for the file. | 479 | * @path contains the path structure for the file. |
481 | * Return 0 if permission is granted. | 480 | * Return 0 if permission is granted. |
482 | * @inode_getattr: | 481 | * @inode_getattr: |
483 | * Check permission before obtaining file attributes. | 482 | * Check permission before obtaining file attributes. |
484 | * @mnt is the vfsmount where the dentry was looked up | 483 | * @mnt is the vfsmount where the dentry was looked up |
485 | * @dentry contains the dentry structure for the file. | 484 | * @dentry contains the dentry structure for the file. |
486 | * Return 0 if permission is granted. | 485 | * Return 0 if permission is granted. |
487 | * @inode_setxattr: | 486 | * @inode_setxattr: |
488 | * Check permission before setting the extended attributes | 487 | * Check permission before setting the extended attributes |
489 | * @value identified by @name for @dentry. | 488 | * @value identified by @name for @dentry. |
490 | * Return 0 if permission is granted. | 489 | * Return 0 if permission is granted. |
491 | * @inode_post_setxattr: | 490 | * @inode_post_setxattr: |
492 | * Update inode security field after successful setxattr operation. | 491 | * Update inode security field after successful setxattr operation. |
493 | * @value identified by @name for @dentry. | 492 | * @value identified by @name for @dentry. |
494 | * @inode_getxattr: | 493 | * @inode_getxattr: |
495 | * Check permission before obtaining the extended attributes | 494 | * Check permission before obtaining the extended attributes |
496 | * identified by @name for @dentry. | 495 | * identified by @name for @dentry. |
497 | * Return 0 if permission is granted. | 496 | * Return 0 if permission is granted. |
498 | * @inode_listxattr: | 497 | * @inode_listxattr: |
499 | * Check permission before obtaining the list of extended attribute | 498 | * Check permission before obtaining the list of extended attribute |
500 | * names for @dentry. | 499 | * names for @dentry. |
501 | * Return 0 if permission is granted. | 500 | * Return 0 if permission is granted. |
502 | * @inode_removexattr: | 501 | * @inode_removexattr: |
503 | * Check permission before removing the extended attribute | 502 | * Check permission before removing the extended attribute |
504 | * identified by @name for @dentry. | 503 | * identified by @name for @dentry. |
505 | * Return 0 if permission is granted. | 504 | * Return 0 if permission is granted. |
506 | * @inode_getsecurity: | 505 | * @inode_getsecurity: |
507 | * Retrieve a copy of the extended attribute representation of the | 506 | * Retrieve a copy of the extended attribute representation of the |
508 | * security label associated with @name for @inode via @buffer. Note that | 507 | * security label associated with @name for @inode via @buffer. Note that |
509 | * @name is the remainder of the attribute name after the security prefix | 508 | * @name is the remainder of the attribute name after the security prefix |
510 | * has been removed. @alloc is used to specify of the call should return a | 509 | * has been removed. @alloc is used to specify of the call should return a |
511 | * value via the buffer or just the value length Return size of buffer on | 510 | * value via the buffer or just the value length Return size of buffer on |
512 | * success. | 511 | * success. |
513 | * @inode_setsecurity: | 512 | * @inode_setsecurity: |
514 | * Set the security label associated with @name for @inode from the | 513 | * Set the security label associated with @name for @inode from the |
515 | * extended attribute value @value. @size indicates the size of the | 514 | * extended attribute value @value. @size indicates the size of the |
516 | * @value in bytes. @flags may be XATTR_CREATE, XATTR_REPLACE, or 0. | 515 | * @value in bytes. @flags may be XATTR_CREATE, XATTR_REPLACE, or 0. |
517 | * Note that @name is the remainder of the attribute name after the | 516 | * Note that @name is the remainder of the attribute name after the |
518 | * security. prefix has been removed. | 517 | * security. prefix has been removed. |
519 | * Return 0 on success. | 518 | * Return 0 on success. |
520 | * @inode_listsecurity: | 519 | * @inode_listsecurity: |
521 | * Copy the extended attribute names for the security labels | 520 | * Copy the extended attribute names for the security labels |
522 | * associated with @inode into @buffer. The maximum size of @buffer | 521 | * associated with @inode into @buffer. The maximum size of @buffer |
523 | * is specified by @buffer_size. @buffer may be NULL to request | 522 | * is specified by @buffer_size. @buffer may be NULL to request |
524 | * the size of the buffer required. | 523 | * the size of the buffer required. |
525 | * Returns number of bytes used/required on success. | 524 | * Returns number of bytes used/required on success. |
526 | * @inode_need_killpriv: | 525 | * @inode_need_killpriv: |
527 | * Called when an inode has been changed. | 526 | * Called when an inode has been changed. |
528 | * @dentry is the dentry being changed. | 527 | * @dentry is the dentry being changed. |
529 | * Return <0 on error to abort the inode change operation. | 528 | * Return <0 on error to abort the inode change operation. |
530 | * Return 0 if inode_killpriv does not need to be called. | 529 | * Return 0 if inode_killpriv does not need to be called. |
531 | * Return >0 if inode_killpriv does need to be called. | 530 | * Return >0 if inode_killpriv does need to be called. |
532 | * @inode_killpriv: | 531 | * @inode_killpriv: |
533 | * The setuid bit is being removed. Remove similar security labels. | 532 | * The setuid bit is being removed. Remove similar security labels. |
534 | * Called with the dentry->d_inode->i_mutex held. | 533 | * Called with the dentry->d_inode->i_mutex held. |
535 | * @dentry is the dentry being changed. | 534 | * @dentry is the dentry being changed. |
536 | * Return 0 on success. If error is returned, then the operation | 535 | * Return 0 on success. If error is returned, then the operation |
537 | * causing setuid bit removal is failed. | 536 | * causing setuid bit removal is failed. |
538 | * @inode_getsecid: | 537 | * @inode_getsecid: |
539 | * Get the secid associated with the node. | 538 | * Get the secid associated with the node. |
540 | * @inode contains a pointer to the inode. | 539 | * @inode contains a pointer to the inode. |
541 | * @secid contains a pointer to the location where result will be saved. | 540 | * @secid contains a pointer to the location where result will be saved. |
542 | * In case of failure, @secid will be set to zero. | 541 | * In case of failure, @secid will be set to zero. |
543 | * | 542 | * |
544 | * Security hooks for file operations | 543 | * Security hooks for file operations |
545 | * | 544 | * |
546 | * @file_permission: | 545 | * @file_permission: |
547 | * Check file permissions before accessing an open file. This hook is | 546 | * Check file permissions before accessing an open file. This hook is |
548 | * called by various operations that read or write files. A security | 547 | * called by various operations that read or write files. A security |
549 | * module can use this hook to perform additional checking on these | 548 | * module can use this hook to perform additional checking on these |
550 | * operations, e.g. to revalidate permissions on use to support privilege | 549 | * operations, e.g. to revalidate permissions on use to support privilege |
551 | * bracketing or policy changes. Notice that this hook is used when the | 550 | * bracketing or policy changes. Notice that this hook is used when the |
552 | * actual read/write operations are performed, whereas the | 551 | * actual read/write operations are performed, whereas the |
553 | * inode_security_ops hook is called when a file is opened (as well as | 552 | * inode_security_ops hook is called when a file is opened (as well as |
554 | * many other operations). | 553 | * many other operations). |
555 | * Caveat: Although this hook can be used to revalidate permissions for | 554 | * Caveat: Although this hook can be used to revalidate permissions for |
556 | * various system call operations that read or write files, it does not | 555 | * various system call operations that read or write files, it does not |
557 | * address the revalidation of permissions for memory-mapped files. | 556 | * address the revalidation of permissions for memory-mapped files. |
558 | * Security modules must handle this separately if they need such | 557 | * Security modules must handle this separately if they need such |
559 | * revalidation. | 558 | * revalidation. |
560 | * @file contains the file structure being accessed. | 559 | * @file contains the file structure being accessed. |
561 | * @mask contains the requested permissions. | 560 | * @mask contains the requested permissions. |
562 | * Return 0 if permission is granted. | 561 | * Return 0 if permission is granted. |
563 | * @file_alloc_security: | 562 | * @file_alloc_security: |
564 | * Allocate and attach a security structure to the file->f_security field. | 563 | * Allocate and attach a security structure to the file->f_security field. |
565 | * The security field is initialized to NULL when the structure is first | 564 | * The security field is initialized to NULL when the structure is first |
566 | * created. | 565 | * created. |
567 | * @file contains the file structure to secure. | 566 | * @file contains the file structure to secure. |
568 | * Return 0 if the hook is successful and permission is granted. | 567 | * Return 0 if the hook is successful and permission is granted. |
569 | * @file_free_security: | 568 | * @file_free_security: |
570 | * Deallocate and free any security structures stored in file->f_security. | 569 | * Deallocate and free any security structures stored in file->f_security. |
571 | * @file contains the file structure being modified. | 570 | * @file contains the file structure being modified. |
572 | * @file_ioctl: | 571 | * @file_ioctl: |
573 | * @file contains the file structure. | 572 | * @file contains the file structure. |
574 | * @cmd contains the operation to perform. | 573 | * @cmd contains the operation to perform. |
575 | * @arg contains the operational arguments. | 574 | * @arg contains the operational arguments. |
576 | * Check permission for an ioctl operation on @file. Note that @arg can | 575 | * Check permission for an ioctl operation on @file. Note that @arg can |
577 | * sometimes represents a user space pointer; in other cases, it may be a | 576 | * sometimes represents a user space pointer; in other cases, it may be a |
578 | * simple integer value. When @arg represents a user space pointer, it | 577 | * simple integer value. When @arg represents a user space pointer, it |
579 | * should never be used by the security module. | 578 | * should never be used by the security module. |
580 | * Return 0 if permission is granted. | 579 | * Return 0 if permission is granted. |
581 | * @file_mmap : | 580 | * @file_mmap : |
582 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | 581 | * Check permissions for a mmap operation. The @file may be NULL, e.g. |
583 | * if mapping anonymous memory. | 582 | * if mapping anonymous memory. |
584 | * @file contains the file structure for file to map (may be NULL). | 583 | * @file contains the file structure for file to map (may be NULL). |
585 | * @reqprot contains the protection requested by the application. | 584 | * @reqprot contains the protection requested by the application. |
586 | * @prot contains the protection that will be applied by the kernel. | 585 | * @prot contains the protection that will be applied by the kernel. |
587 | * @flags contains the operational flags. | 586 | * @flags contains the operational flags. |
588 | * Return 0 if permission is granted. | 587 | * Return 0 if permission is granted. |
589 | * @file_mprotect: | 588 | * @file_mprotect: |
590 | * Check permissions before changing memory access permissions. | 589 | * Check permissions before changing memory access permissions. |
591 | * @vma contains the memory region to modify. | 590 | * @vma contains the memory region to modify. |
592 | * @reqprot contains the protection requested by the application. | 591 | * @reqprot contains the protection requested by the application. |
593 | * @prot contains the protection that will be applied by the kernel. | 592 | * @prot contains the protection that will be applied by the kernel. |
594 | * Return 0 if permission is granted. | 593 | * Return 0 if permission is granted. |
595 | * @file_lock: | 594 | * @file_lock: |
596 | * Check permission before performing file locking operations. | 595 | * Check permission before performing file locking operations. |
597 | * Note: this hook mediates both flock and fcntl style locks. | 596 | * Note: this hook mediates both flock and fcntl style locks. |
598 | * @file contains the file structure. | 597 | * @file contains the file structure. |
599 | * @cmd contains the posix-translated lock operation to perform | 598 | * @cmd contains the posix-translated lock operation to perform |
600 | * (e.g. F_RDLCK, F_WRLCK). | 599 | * (e.g. F_RDLCK, F_WRLCK). |
601 | * Return 0 if permission is granted. | 600 | * Return 0 if permission is granted. |
602 | * @file_fcntl: | 601 | * @file_fcntl: |
603 | * Check permission before allowing the file operation specified by @cmd | 602 | * Check permission before allowing the file operation specified by @cmd |
604 | * from being performed on the file @file. Note that @arg can sometimes | 603 | * from being performed on the file @file. Note that @arg can sometimes |
605 | * represents a user space pointer; in other cases, it may be a simple | 604 | * represents a user space pointer; in other cases, it may be a simple |
606 | * integer value. When @arg represents a user space pointer, it should | 605 | * integer value. When @arg represents a user space pointer, it should |
607 | * never be used by the security module. | 606 | * never be used by the security module. |
608 | * @file contains the file structure. | 607 | * @file contains the file structure. |
609 | * @cmd contains the operation to be performed. | 608 | * @cmd contains the operation to be performed. |
610 | * @arg contains the operational arguments. | 609 | * @arg contains the operational arguments. |
611 | * Return 0 if permission is granted. | 610 | * Return 0 if permission is granted. |
612 | * @file_set_fowner: | 611 | * @file_set_fowner: |
613 | * Save owner security information (typically from current->security) in | 612 | * Save owner security information (typically from current->security) in |
614 | * file->f_security for later use by the send_sigiotask hook. | 613 | * file->f_security for later use by the send_sigiotask hook. |
615 | * @file contains the file structure to update. | 614 | * @file contains the file structure to update. |
616 | * Return 0 on success. | 615 | * Return 0 on success. |
617 | * @file_send_sigiotask: | 616 | * @file_send_sigiotask: |
618 | * Check permission for the file owner @fown to send SIGIO or SIGURG to the | 617 | * Check permission for the file owner @fown to send SIGIO or SIGURG to the |
619 | * process @tsk. Note that this hook is sometimes called from interrupt. | 618 | * process @tsk. Note that this hook is sometimes called from interrupt. |
620 | * Note that the fown_struct, @fown, is never outside the context of a | 619 | * Note that the fown_struct, @fown, is never outside the context of a |
621 | * struct file, so the file structure (and associated security information) | 620 | * struct file, so the file structure (and associated security information) |
622 | * can always be obtained: | 621 | * can always be obtained: |
623 | * container_of(fown, struct file, f_owner) | 622 | * container_of(fown, struct file, f_owner) |
624 | * @tsk contains the structure of task receiving signal. | 623 | * @tsk contains the structure of task receiving signal. |
625 | * @fown contains the file owner information. | 624 | * @fown contains the file owner information. |
626 | * @sig is the signal that will be sent. When 0, kernel sends SIGIO. | 625 | * @sig is the signal that will be sent. When 0, kernel sends SIGIO. |
627 | * Return 0 if permission is granted. | 626 | * Return 0 if permission is granted. |
628 | * @file_receive: | 627 | * @file_receive: |
629 | * This hook allows security modules to control the ability of a process | 628 | * This hook allows security modules to control the ability of a process |
630 | * to receive an open file descriptor via socket IPC. | 629 | * to receive an open file descriptor via socket IPC. |
631 | * @file contains the file structure being received. | 630 | * @file contains the file structure being received. |
632 | * Return 0 if permission is granted. | 631 | * Return 0 if permission is granted. |
633 | * | 632 | * |
634 | * Security hook for dentry | 633 | * Security hook for dentry |
635 | * | 634 | * |
636 | * @dentry_open | 635 | * @dentry_open |
637 | * Save open-time permission checking state for later use upon | 636 | * Save open-time permission checking state for later use upon |
638 | * file_permission, and recheck access if anything has changed | 637 | * file_permission, and recheck access if anything has changed |
639 | * since inode_permission. | 638 | * since inode_permission. |
640 | * | 639 | * |
641 | * Security hooks for task operations. | 640 | * Security hooks for task operations. |
642 | * | 641 | * |
643 | * @task_create: | 642 | * @task_create: |
644 | * Check permission before creating a child process. See the clone(2) | 643 | * Check permission before creating a child process. See the clone(2) |
645 | * manual page for definitions of the @clone_flags. | 644 | * manual page for definitions of the @clone_flags. |
646 | * @clone_flags contains the flags indicating what should be shared. | 645 | * @clone_flags contains the flags indicating what should be shared. |
647 | * Return 0 if permission is granted. | 646 | * Return 0 if permission is granted. |
648 | * @cred_alloc_blank: | 647 | * @cred_alloc_blank: |
649 | * @cred points to the credentials. | 648 | * @cred points to the credentials. |
650 | * @gfp indicates the atomicity of any memory allocations. | 649 | * @gfp indicates the atomicity of any memory allocations. |
651 | * Only allocate sufficient memory and attach to @cred such that | 650 | * Only allocate sufficient memory and attach to @cred such that |
652 | * cred_transfer() will not get ENOMEM. | 651 | * cred_transfer() will not get ENOMEM. |
653 | * @cred_free: | 652 | * @cred_free: |
654 | * @cred points to the credentials. | 653 | * @cred points to the credentials. |
655 | * Deallocate and clear the cred->security field in a set of credentials. | 654 | * Deallocate and clear the cred->security field in a set of credentials. |
656 | * @cred_prepare: | 655 | * @cred_prepare: |
657 | * @new points to the new credentials. | 656 | * @new points to the new credentials. |
658 | * @old points to the original credentials. | 657 | * @old points to the original credentials. |
659 | * @gfp indicates the atomicity of any memory allocations. | 658 | * @gfp indicates the atomicity of any memory allocations. |
660 | * Prepare a new set of credentials by copying the data from the old set. | 659 | * Prepare a new set of credentials by copying the data from the old set. |
661 | * @cred_transfer: | 660 | * @cred_transfer: |
662 | * @new points to the new credentials. | 661 | * @new points to the new credentials. |
663 | * @old points to the original credentials. | 662 | * @old points to the original credentials. |
664 | * Transfer data from original creds to new creds | 663 | * Transfer data from original creds to new creds |
665 | * @kernel_act_as: | 664 | * @kernel_act_as: |
666 | * Set the credentials for a kernel service to act as (subjective context). | 665 | * Set the credentials for a kernel service to act as (subjective context). |
667 | * @new points to the credentials to be modified. | 666 | * @new points to the credentials to be modified. |
668 | * @secid specifies the security ID to be set | 667 | * @secid specifies the security ID to be set |
669 | * The current task must be the one that nominated @secid. | 668 | * The current task must be the one that nominated @secid. |
670 | * Return 0 if successful. | 669 | * Return 0 if successful. |
671 | * @kernel_create_files_as: | 670 | * @kernel_create_files_as: |
672 | * Set the file creation context in a set of credentials to be the same as | 671 | * Set the file creation context in a set of credentials to be the same as |
673 | * the objective context of the specified inode. | 672 | * the objective context of the specified inode. |
674 | * @new points to the credentials to be modified. | 673 | * @new points to the credentials to be modified. |
675 | * @inode points to the inode to use as a reference. | 674 | * @inode points to the inode to use as a reference. |
676 | * The current task must be the one that nominated @inode. | 675 | * The current task must be the one that nominated @inode. |
677 | * Return 0 if successful. | 676 | * Return 0 if successful. |
678 | * @kernel_module_request: | 677 | * @kernel_module_request: |
679 | * Ability to trigger the kernel to automatically upcall to userspace for | 678 | * Ability to trigger the kernel to automatically upcall to userspace for |
680 | * userspace to load a kernel module with the given name. | 679 | * userspace to load a kernel module with the given name. |
681 | * @kmod_name name of the module requested by the kernel | 680 | * @kmod_name name of the module requested by the kernel |
682 | * Return 0 if successful. | 681 | * Return 0 if successful. |
683 | * @task_fix_setuid: | 682 | * @task_fix_setuid: |
684 | * Update the module's state after setting one or more of the user | 683 | * Update the module's state after setting one or more of the user |
685 | * identity attributes of the current process. The @flags parameter | 684 | * identity attributes of the current process. The @flags parameter |
686 | * indicates which of the set*uid system calls invoked this hook. If | 685 | * indicates which of the set*uid system calls invoked this hook. If |
687 | * @new is the set of credentials that will be installed. Modifications | 686 | * @new is the set of credentials that will be installed. Modifications |
688 | * should be made to this rather than to @current->cred. | 687 | * should be made to this rather than to @current->cred. |
689 | * @old is the set of credentials that are being replaces | 688 | * @old is the set of credentials that are being replaces |
690 | * @flags contains one of the LSM_SETID_* values. | 689 | * @flags contains one of the LSM_SETID_* values. |
691 | * Return 0 on success. | 690 | * Return 0 on success. |
692 | * @task_setpgid: | 691 | * @task_setpgid: |
693 | * Check permission before setting the process group identifier of the | 692 | * Check permission before setting the process group identifier of the |
694 | * process @p to @pgid. | 693 | * process @p to @pgid. |
695 | * @p contains the task_struct for process being modified. | 694 | * @p contains the task_struct for process being modified. |
696 | * @pgid contains the new pgid. | 695 | * @pgid contains the new pgid. |
697 | * Return 0 if permission is granted. | 696 | * Return 0 if permission is granted. |
698 | * @task_getpgid: | 697 | * @task_getpgid: |
699 | * Check permission before getting the process group identifier of the | 698 | * Check permission before getting the process group identifier of the |
700 | * process @p. | 699 | * process @p. |
701 | * @p contains the task_struct for the process. | 700 | * @p contains the task_struct for the process. |
702 | * Return 0 if permission is granted. | 701 | * Return 0 if permission is granted. |
703 | * @task_getsid: | 702 | * @task_getsid: |
704 | * Check permission before getting the session identifier of the process | 703 | * Check permission before getting the session identifier of the process |
705 | * @p. | 704 | * @p. |
706 | * @p contains the task_struct for the process. | 705 | * @p contains the task_struct for the process. |
707 | * Return 0 if permission is granted. | 706 | * Return 0 if permission is granted. |
708 | * @task_getsecid: | 707 | * @task_getsecid: |
709 | * Retrieve the security identifier of the process @p. | 708 | * Retrieve the security identifier of the process @p. |
710 | * @p contains the task_struct for the process and place is into @secid. | 709 | * @p contains the task_struct for the process and place is into @secid. |
711 | * In case of failure, @secid will be set to zero. | 710 | * In case of failure, @secid will be set to zero. |
712 | * | 711 | * |
713 | * @task_setnice: | 712 | * @task_setnice: |
714 | * Check permission before setting the nice value of @p to @nice. | 713 | * Check permission before setting the nice value of @p to @nice. |
715 | * @p contains the task_struct of process. | 714 | * @p contains the task_struct of process. |
716 | * @nice contains the new nice value. | 715 | * @nice contains the new nice value. |
717 | * Return 0 if permission is granted. | 716 | * Return 0 if permission is granted. |
718 | * @task_setioprio | 717 | * @task_setioprio |
719 | * Check permission before setting the ioprio value of @p to @ioprio. | 718 | * Check permission before setting the ioprio value of @p to @ioprio. |
720 | * @p contains the task_struct of process. | 719 | * @p contains the task_struct of process. |
721 | * @ioprio contains the new ioprio value | 720 | * @ioprio contains the new ioprio value |
722 | * Return 0 if permission is granted. | 721 | * Return 0 if permission is granted. |
723 | * @task_getioprio | 722 | * @task_getioprio |
724 | * Check permission before getting the ioprio value of @p. | 723 | * Check permission before getting the ioprio value of @p. |
725 | * @p contains the task_struct of process. | 724 | * @p contains the task_struct of process. |
726 | * Return 0 if permission is granted. | 725 | * Return 0 if permission is granted. |
727 | * @task_setrlimit: | 726 | * @task_setrlimit: |
728 | * Check permission before setting the resource limits of the current | 727 | * Check permission before setting the resource limits of the current |
729 | * process for @resource to @new_rlim. The old resource limit values can | 728 | * process for @resource to @new_rlim. The old resource limit values can |
730 | * be examined by dereferencing (current->signal->rlim + resource). | 729 | * be examined by dereferencing (current->signal->rlim + resource). |
731 | * @resource contains the resource whose limit is being set. | 730 | * @resource contains the resource whose limit is being set. |
732 | * @new_rlim contains the new limits for @resource. | 731 | * @new_rlim contains the new limits for @resource. |
733 | * Return 0 if permission is granted. | 732 | * Return 0 if permission is granted. |
734 | * @task_setscheduler: | 733 | * @task_setscheduler: |
735 | * Check permission before setting scheduling policy and/or parameters of | 734 | * Check permission before setting scheduling policy and/or parameters of |
736 | * process @p based on @policy and @lp. | 735 | * process @p based on @policy and @lp. |
737 | * @p contains the task_struct for process. | 736 | * @p contains the task_struct for process. |
738 | * @policy contains the scheduling policy. | 737 | * @policy contains the scheduling policy. |
739 | * @lp contains the scheduling parameters. | 738 | * @lp contains the scheduling parameters. |
740 | * Return 0 if permission is granted. | 739 | * Return 0 if permission is granted. |
741 | * @task_getscheduler: | 740 | * @task_getscheduler: |
742 | * Check permission before obtaining scheduling information for process | 741 | * Check permission before obtaining scheduling information for process |
743 | * @p. | 742 | * @p. |
744 | * @p contains the task_struct for process. | 743 | * @p contains the task_struct for process. |
745 | * Return 0 if permission is granted. | 744 | * Return 0 if permission is granted. |
746 | * @task_movememory | 745 | * @task_movememory |
747 | * Check permission before moving memory owned by process @p. | 746 | * Check permission before moving memory owned by process @p. |
748 | * @p contains the task_struct for process. | 747 | * @p contains the task_struct for process. |
749 | * Return 0 if permission is granted. | 748 | * Return 0 if permission is granted. |
750 | * @task_kill: | 749 | * @task_kill: |
751 | * Check permission before sending signal @sig to @p. @info can be NULL, | 750 | * Check permission before sending signal @sig to @p. @info can be NULL, |
752 | * the constant 1, or a pointer to a siginfo structure. If @info is 1 or | 751 | * the constant 1, or a pointer to a siginfo structure. If @info is 1 or |
753 | * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming | 752 | * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming |
754 | * from the kernel and should typically be permitted. | 753 | * from the kernel and should typically be permitted. |
755 | * SIGIO signals are handled separately by the send_sigiotask hook in | 754 | * SIGIO signals are handled separately by the send_sigiotask hook in |
756 | * file_security_ops. | 755 | * file_security_ops. |
757 | * @p contains the task_struct for process. | 756 | * @p contains the task_struct for process. |
758 | * @info contains the signal information. | 757 | * @info contains the signal information. |
759 | * @sig contains the signal value. | 758 | * @sig contains the signal value. |
760 | * @secid contains the sid of the process where the signal originated | 759 | * @secid contains the sid of the process where the signal originated |
761 | * Return 0 if permission is granted. | 760 | * Return 0 if permission is granted. |
762 | * @task_wait: | 761 | * @task_wait: |
763 | * Check permission before allowing a process to reap a child process @p | 762 | * Check permission before allowing a process to reap a child process @p |
764 | * and collect its status information. | 763 | * and collect its status information. |
765 | * @p contains the task_struct for process. | 764 | * @p contains the task_struct for process. |
766 | * Return 0 if permission is granted. | 765 | * Return 0 if permission is granted. |
767 | * @task_prctl: | 766 | * @task_prctl: |
768 | * Check permission before performing a process control operation on the | 767 | * Check permission before performing a process control operation on the |
769 | * current process. | 768 | * current process. |
770 | * @option contains the operation. | 769 | * @option contains the operation. |
771 | * @arg2 contains a argument. | 770 | * @arg2 contains a argument. |
772 | * @arg3 contains a argument. | 771 | * @arg3 contains a argument. |
773 | * @arg4 contains a argument. | 772 | * @arg4 contains a argument. |
774 | * @arg5 contains a argument. | 773 | * @arg5 contains a argument. |
775 | * Return -ENOSYS if no-one wanted to handle this op, any other value to | 774 | * Return -ENOSYS if no-one wanted to handle this op, any other value to |
776 | * cause prctl() to return immediately with that value. | 775 | * cause prctl() to return immediately with that value. |
777 | * @task_to_inode: | 776 | * @task_to_inode: |
778 | * Set the security attributes for an inode based on an associated task's | 777 | * Set the security attributes for an inode based on an associated task's |
779 | * security attributes, e.g. for /proc/pid inodes. | 778 | * security attributes, e.g. for /proc/pid inodes. |
780 | * @p contains the task_struct for the task. | 779 | * @p contains the task_struct for the task. |
781 | * @inode contains the inode structure for the inode. | 780 | * @inode contains the inode structure for the inode. |
782 | * | 781 | * |
783 | * Security hooks for Netlink messaging. | 782 | * Security hooks for Netlink messaging. |
784 | * | 783 | * |
785 | * @netlink_send: | 784 | * @netlink_send: |
786 | * Save security information for a netlink message so that permission | 785 | * Save security information for a netlink message so that permission |
787 | * checking can be performed when the message is processed. The security | 786 | * checking can be performed when the message is processed. The security |
788 | * information can be saved using the eff_cap field of the | 787 | * information can be saved using the eff_cap field of the |
789 | * netlink_skb_parms structure. Also may be used to provide fine | 788 | * netlink_skb_parms structure. Also may be used to provide fine |
790 | * grained control over message transmission. | 789 | * grained control over message transmission. |
791 | * @sk associated sock of task sending the message., | 790 | * @sk associated sock of task sending the message., |
792 | * @skb contains the sk_buff structure for the netlink message. | 791 | * @skb contains the sk_buff structure for the netlink message. |
793 | * Return 0 if the information was successfully saved and message | 792 | * Return 0 if the information was successfully saved and message |
794 | * is allowed to be transmitted. | 793 | * is allowed to be transmitted. |
795 | * @netlink_recv: | ||
796 | * Check permission before processing the received netlink message in | ||
797 | * @skb. | ||
798 | * @skb contains the sk_buff structure for the netlink message. | ||
799 | * @cap indicates the capability required | ||
800 | * Return 0 if permission is granted. | ||
801 | * | 794 | * |
802 | * Security hooks for Unix domain networking. | 795 | * Security hooks for Unix domain networking. |
803 | * | 796 | * |
804 | * @unix_stream_connect: | 797 | * @unix_stream_connect: |
805 | * Check permissions before establishing a Unix domain stream connection | 798 | * Check permissions before establishing a Unix domain stream connection |
806 | * between @sock and @other. | 799 | * between @sock and @other. |
807 | * @sock contains the sock structure. | 800 | * @sock contains the sock structure. |
808 | * @other contains the peer sock structure. | 801 | * @other contains the peer sock structure. |
809 | * @newsk contains the new sock structure. | 802 | * @newsk contains the new sock structure. |
810 | * Return 0 if permission is granted. | 803 | * Return 0 if permission is granted. |
811 | * @unix_may_send: | 804 | * @unix_may_send: |
812 | * Check permissions before connecting or sending datagrams from @sock to | 805 | * Check permissions before connecting or sending datagrams from @sock to |
813 | * @other. | 806 | * @other. |
814 | * @sock contains the socket structure. | 807 | * @sock contains the socket structure. |
815 | * @sock contains the peer socket structure. | 808 | * @sock contains the peer socket structure. |
816 | * Return 0 if permission is granted. | 809 | * Return 0 if permission is granted. |
817 | * | 810 | * |
818 | * The @unix_stream_connect and @unix_may_send hooks were necessary because | 811 | * The @unix_stream_connect and @unix_may_send hooks were necessary because |
819 | * Linux provides an alternative to the conventional file name space for Unix | 812 | * Linux provides an alternative to the conventional file name space for Unix |
820 | * domain sockets. Whereas binding and connecting to sockets in the file name | 813 | * domain sockets. Whereas binding and connecting to sockets in the file name |
821 | * space is mediated by the typical file permissions (and caught by the mknod | 814 | * space is mediated by the typical file permissions (and caught by the mknod |
822 | * and permission hooks in inode_security_ops), binding and connecting to | 815 | * and permission hooks in inode_security_ops), binding and connecting to |
823 | * sockets in the abstract name space is completely unmediated. Sufficient | 816 | * sockets in the abstract name space is completely unmediated. Sufficient |
824 | * control of Unix domain sockets in the abstract name space isn't possible | 817 | * control of Unix domain sockets in the abstract name space isn't possible |
825 | * using only the socket layer hooks, since we need to know the actual target | 818 | * using only the socket layer hooks, since we need to know the actual target |
826 | * socket, which is not looked up until we are inside the af_unix code. | 819 | * socket, which is not looked up until we are inside the af_unix code. |
827 | * | 820 | * |
828 | * Security hooks for socket operations. | 821 | * Security hooks for socket operations. |
829 | * | 822 | * |
830 | * @socket_create: | 823 | * @socket_create: |
831 | * Check permissions prior to creating a new socket. | 824 | * Check permissions prior to creating a new socket. |
832 | * @family contains the requested protocol family. | 825 | * @family contains the requested protocol family. |
833 | * @type contains the requested communications type. | 826 | * @type contains the requested communications type. |
834 | * @protocol contains the requested protocol. | 827 | * @protocol contains the requested protocol. |
835 | * @kern set to 1 if a kernel socket. | 828 | * @kern set to 1 if a kernel socket. |
836 | * Return 0 if permission is granted. | 829 | * Return 0 if permission is granted. |
837 | * @socket_post_create: | 830 | * @socket_post_create: |
838 | * This hook allows a module to update or allocate a per-socket security | 831 | * This hook allows a module to update or allocate a per-socket security |
839 | * structure. Note that the security field was not added directly to the | 832 | * structure. Note that the security field was not added directly to the |
840 | * socket structure, but rather, the socket security information is stored | 833 | * socket structure, but rather, the socket security information is stored |
841 | * in the associated inode. Typically, the inode alloc_security hook will | 834 | * in the associated inode. Typically, the inode alloc_security hook will |
842 | * allocate and and attach security information to | 835 | * allocate and and attach security information to |
843 | * sock->inode->i_security. This hook may be used to update the | 836 | * sock->inode->i_security. This hook may be used to update the |
844 | * sock->inode->i_security field with additional information that wasn't | 837 | * sock->inode->i_security field with additional information that wasn't |
845 | * available when the inode was allocated. | 838 | * available when the inode was allocated. |
846 | * @sock contains the newly created socket structure. | 839 | * @sock contains the newly created socket structure. |
847 | * @family contains the requested protocol family. | 840 | * @family contains the requested protocol family. |
848 | * @type contains the requested communications type. | 841 | * @type contains the requested communications type. |
849 | * @protocol contains the requested protocol. | 842 | * @protocol contains the requested protocol. |
850 | * @kern set to 1 if a kernel socket. | 843 | * @kern set to 1 if a kernel socket. |
851 | * @socket_bind: | 844 | * @socket_bind: |
852 | * Check permission before socket protocol layer bind operation is | 845 | * Check permission before socket protocol layer bind operation is |
853 | * performed and the socket @sock is bound to the address specified in the | 846 | * performed and the socket @sock is bound to the address specified in the |
854 | * @address parameter. | 847 | * @address parameter. |
855 | * @sock contains the socket structure. | 848 | * @sock contains the socket structure. |
856 | * @address contains the address to bind to. | 849 | * @address contains the address to bind to. |
857 | * @addrlen contains the length of address. | 850 | * @addrlen contains the length of address. |
858 | * Return 0 if permission is granted. | 851 | * Return 0 if permission is granted. |
859 | * @socket_connect: | 852 | * @socket_connect: |
860 | * Check permission before socket protocol layer connect operation | 853 | * Check permission before socket protocol layer connect operation |
861 | * attempts to connect socket @sock to a remote address, @address. | 854 | * attempts to connect socket @sock to a remote address, @address. |
862 | * @sock contains the socket structure. | 855 | * @sock contains the socket structure. |
863 | * @address contains the address of remote endpoint. | 856 | * @address contains the address of remote endpoint. |
864 | * @addrlen contains the length of address. | 857 | * @addrlen contains the length of address. |
865 | * Return 0 if permission is granted. | 858 | * Return 0 if permission is granted. |
866 | * @socket_listen: | 859 | * @socket_listen: |
867 | * Check permission before socket protocol layer listen operation. | 860 | * Check permission before socket protocol layer listen operation. |
868 | * @sock contains the socket structure. | 861 | * @sock contains the socket structure. |
869 | * @backlog contains the maximum length for the pending connection queue. | 862 | * @backlog contains the maximum length for the pending connection queue. |
870 | * Return 0 if permission is granted. | 863 | * Return 0 if permission is granted. |
871 | * @socket_accept: | 864 | * @socket_accept: |
872 | * Check permission before accepting a new connection. Note that the new | 865 | * Check permission before accepting a new connection. Note that the new |
873 | * socket, @newsock, has been created and some information copied to it, | 866 | * socket, @newsock, has been created and some information copied to it, |
874 | * but the accept operation has not actually been performed. | 867 | * but the accept operation has not actually been performed. |
875 | * @sock contains the listening socket structure. | 868 | * @sock contains the listening socket structure. |
876 | * @newsock contains the newly created server socket for connection. | 869 | * @newsock contains the newly created server socket for connection. |
877 | * Return 0 if permission is granted. | 870 | * Return 0 if permission is granted. |
878 | * @socket_sendmsg: | 871 | * @socket_sendmsg: |
879 | * Check permission before transmitting a message to another socket. | 872 | * Check permission before transmitting a message to another socket. |
880 | * @sock contains the socket structure. | 873 | * @sock contains the socket structure. |
881 | * @msg contains the message to be transmitted. | 874 | * @msg contains the message to be transmitted. |
882 | * @size contains the size of message. | 875 | * @size contains the size of message. |
883 | * Return 0 if permission is granted. | 876 | * Return 0 if permission is granted. |
884 | * @socket_recvmsg: | 877 | * @socket_recvmsg: |
885 | * Check permission before receiving a message from a socket. | 878 | * Check permission before receiving a message from a socket. |
886 | * @sock contains the socket structure. | 879 | * @sock contains the socket structure. |
887 | * @msg contains the message structure. | 880 | * @msg contains the message structure. |
888 | * @size contains the size of message structure. | 881 | * @size contains the size of message structure. |
889 | * @flags contains the operational flags. | 882 | * @flags contains the operational flags. |
890 | * Return 0 if permission is granted. | 883 | * Return 0 if permission is granted. |
891 | * @socket_getsockname: | 884 | * @socket_getsockname: |
892 | * Check permission before the local address (name) of the socket object | 885 | * Check permission before the local address (name) of the socket object |
893 | * @sock is retrieved. | 886 | * @sock is retrieved. |
894 | * @sock contains the socket structure. | 887 | * @sock contains the socket structure. |
895 | * Return 0 if permission is granted. | 888 | * Return 0 if permission is granted. |
896 | * @socket_getpeername: | 889 | * @socket_getpeername: |
897 | * Check permission before the remote address (name) of a socket object | 890 | * Check permission before the remote address (name) of a socket object |
898 | * @sock is retrieved. | 891 | * @sock is retrieved. |
899 | * @sock contains the socket structure. | 892 | * @sock contains the socket structure. |
900 | * Return 0 if permission is granted. | 893 | * Return 0 if permission is granted. |
901 | * @socket_getsockopt: | 894 | * @socket_getsockopt: |
902 | * Check permissions before retrieving the options associated with socket | 895 | * Check permissions before retrieving the options associated with socket |
903 | * @sock. | 896 | * @sock. |
904 | * @sock contains the socket structure. | 897 | * @sock contains the socket structure. |
905 | * @level contains the protocol level to retrieve option from. | 898 | * @level contains the protocol level to retrieve option from. |
906 | * @optname contains the name of option to retrieve. | 899 | * @optname contains the name of option to retrieve. |
907 | * Return 0 if permission is granted. | 900 | * Return 0 if permission is granted. |
908 | * @socket_setsockopt: | 901 | * @socket_setsockopt: |
909 | * Check permissions before setting the options associated with socket | 902 | * Check permissions before setting the options associated with socket |
910 | * @sock. | 903 | * @sock. |
911 | * @sock contains the socket structure. | 904 | * @sock contains the socket structure. |
912 | * @level contains the protocol level to set options for. | 905 | * @level contains the protocol level to set options for. |
913 | * @optname contains the name of the option to set. | 906 | * @optname contains the name of the option to set. |
914 | * Return 0 if permission is granted. | 907 | * Return 0 if permission is granted. |
915 | * @socket_shutdown: | 908 | * @socket_shutdown: |
916 | * Checks permission before all or part of a connection on the socket | 909 | * Checks permission before all or part of a connection on the socket |
917 | * @sock is shut down. | 910 | * @sock is shut down. |
918 | * @sock contains the socket structure. | 911 | * @sock contains the socket structure. |
919 | * @how contains the flag indicating how future sends and receives are handled. | 912 | * @how contains the flag indicating how future sends and receives are handled. |
920 | * Return 0 if permission is granted. | 913 | * Return 0 if permission is granted. |
921 | * @socket_sock_rcv_skb: | 914 | * @socket_sock_rcv_skb: |
922 | * Check permissions on incoming network packets. This hook is distinct | 915 | * Check permissions on incoming network packets. This hook is distinct |
923 | * from Netfilter's IP input hooks since it is the first time that the | 916 | * from Netfilter's IP input hooks since it is the first time that the |
924 | * incoming sk_buff @skb has been associated with a particular socket, @sk. | 917 | * incoming sk_buff @skb has been associated with a particular socket, @sk. |
925 | * Must not sleep inside this hook because some callers hold spinlocks. | 918 | * Must not sleep inside this hook because some callers hold spinlocks. |
926 | * @sk contains the sock (not socket) associated with the incoming sk_buff. | 919 | * @sk contains the sock (not socket) associated with the incoming sk_buff. |
927 | * @skb contains the incoming network data. | 920 | * @skb contains the incoming network data. |
928 | * @socket_getpeersec_stream: | 921 | * @socket_getpeersec_stream: |
929 | * This hook allows the security module to provide peer socket security | 922 | * This hook allows the security module to provide peer socket security |
930 | * state for unix or connected tcp sockets to userspace via getsockopt | 923 | * state for unix or connected tcp sockets to userspace via getsockopt |
931 | * SO_GETPEERSEC. For tcp sockets this can be meaningful if the | 924 | * SO_GETPEERSEC. For tcp sockets this can be meaningful if the |
932 | * socket is associated with an ipsec SA. | 925 | * socket is associated with an ipsec SA. |
933 | * @sock is the local socket. | 926 | * @sock is the local socket. |
934 | * @optval userspace memory where the security state is to be copied. | 927 | * @optval userspace memory where the security state is to be copied. |
935 | * @optlen userspace int where the module should copy the actual length | 928 | * @optlen userspace int where the module should copy the actual length |
936 | * of the security state. | 929 | * of the security state. |
937 | * @len as input is the maximum length to copy to userspace provided | 930 | * @len as input is the maximum length to copy to userspace provided |
938 | * by the caller. | 931 | * by the caller. |
939 | * Return 0 if all is well, otherwise, typical getsockopt return | 932 | * Return 0 if all is well, otherwise, typical getsockopt return |
940 | * values. | 933 | * values. |
941 | * @socket_getpeersec_dgram: | 934 | * @socket_getpeersec_dgram: |
942 | * This hook allows the security module to provide peer socket security | 935 | * This hook allows the security module to provide peer socket security |
943 | * state for udp sockets on a per-packet basis to userspace via | 936 | * state for udp sockets on a per-packet basis to userspace via |
944 | * getsockopt SO_GETPEERSEC. The application must first have indicated | 937 | * getsockopt SO_GETPEERSEC. The application must first have indicated |
945 | * the IP_PASSSEC option via getsockopt. It can then retrieve the | 938 | * the IP_PASSSEC option via getsockopt. It can then retrieve the |
946 | * security state returned by this hook for a packet via the SCM_SECURITY | 939 | * security state returned by this hook for a packet via the SCM_SECURITY |
947 | * ancillary message type. | 940 | * ancillary message type. |
948 | * @skb is the skbuff for the packet being queried | 941 | * @skb is the skbuff for the packet being queried |
949 | * @secdata is a pointer to a buffer in which to copy the security data | 942 | * @secdata is a pointer to a buffer in which to copy the security data |
950 | * @seclen is the maximum length for @secdata | 943 | * @seclen is the maximum length for @secdata |
951 | * Return 0 on success, error on failure. | 944 | * Return 0 on success, error on failure. |
952 | * @sk_alloc_security: | 945 | * @sk_alloc_security: |
953 | * Allocate and attach a security structure to the sk->sk_security field, | 946 | * Allocate and attach a security structure to the sk->sk_security field, |
954 | * which is used to copy security attributes between local stream sockets. | 947 | * which is used to copy security attributes between local stream sockets. |
955 | * @sk_free_security: | 948 | * @sk_free_security: |
956 | * Deallocate security structure. | 949 | * Deallocate security structure. |
957 | * @sk_clone_security: | 950 | * @sk_clone_security: |
958 | * Clone/copy security structure. | 951 | * Clone/copy security structure. |
959 | * @sk_getsecid: | 952 | * @sk_getsecid: |
960 | * Retrieve the LSM-specific secid for the sock to enable caching of network | 953 | * Retrieve the LSM-specific secid for the sock to enable caching of network |
961 | * authorizations. | 954 | * authorizations. |
962 | * @sock_graft: | 955 | * @sock_graft: |
963 | * Sets the socket's isec sid to the sock's sid. | 956 | * Sets the socket's isec sid to the sock's sid. |
964 | * @inet_conn_request: | 957 | * @inet_conn_request: |
965 | * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid. | 958 | * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid. |
966 | * @inet_csk_clone: | 959 | * @inet_csk_clone: |
967 | * Sets the new child socket's sid to the openreq sid. | 960 | * Sets the new child socket's sid to the openreq sid. |
968 | * @inet_conn_established: | 961 | * @inet_conn_established: |
969 | * Sets the connection's peersid to the secmark on skb. | 962 | * Sets the connection's peersid to the secmark on skb. |
970 | * @secmark_relabel_packet: | 963 | * @secmark_relabel_packet: |
971 | * check if the process should be allowed to relabel packets to the given secid | 964 | * check if the process should be allowed to relabel packets to the given secid |
972 | * @security_secmark_refcount_inc | 965 | * @security_secmark_refcount_inc |
973 | * tells the LSM to increment the number of secmark labeling rules loaded | 966 | * tells the LSM to increment the number of secmark labeling rules loaded |
974 | * @security_secmark_refcount_dec | 967 | * @security_secmark_refcount_dec |
975 | * tells the LSM to decrement the number of secmark labeling rules loaded | 968 | * tells the LSM to decrement the number of secmark labeling rules loaded |
976 | * @req_classify_flow: | 969 | * @req_classify_flow: |
977 | * Sets the flow's sid to the openreq sid. | 970 | * Sets the flow's sid to the openreq sid. |
978 | * @tun_dev_create: | 971 | * @tun_dev_create: |
979 | * Check permissions prior to creating a new TUN device. | 972 | * Check permissions prior to creating a new TUN device. |
980 | * @tun_dev_post_create: | 973 | * @tun_dev_post_create: |
981 | * This hook allows a module to update or allocate a per-socket security | 974 | * This hook allows a module to update or allocate a per-socket security |
982 | * structure. | 975 | * structure. |
983 | * @sk contains the newly created sock structure. | 976 | * @sk contains the newly created sock structure. |
984 | * @tun_dev_attach: | 977 | * @tun_dev_attach: |
985 | * Check permissions prior to attaching to a persistent TUN device. This | 978 | * Check permissions prior to attaching to a persistent TUN device. This |
986 | * hook can also be used by the module to update any security state | 979 | * hook can also be used by the module to update any security state |
987 | * associated with the TUN device's sock structure. | 980 | * associated with the TUN device's sock structure. |
988 | * @sk contains the existing sock structure. | 981 | * @sk contains the existing sock structure. |
989 | * | 982 | * |
990 | * Security hooks for XFRM operations. | 983 | * Security hooks for XFRM operations. |
991 | * | 984 | * |
992 | * @xfrm_policy_alloc_security: | 985 | * @xfrm_policy_alloc_security: |
993 | * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy | 986 | * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy |
994 | * Database used by the XFRM system. | 987 | * Database used by the XFRM system. |
995 | * @sec_ctx contains the security context information being provided by | 988 | * @sec_ctx contains the security context information being provided by |
996 | * the user-level policy update program (e.g., setkey). | 989 | * the user-level policy update program (e.g., setkey). |
997 | * Allocate a security structure to the xp->security field; the security | 990 | * Allocate a security structure to the xp->security field; the security |
998 | * field is initialized to NULL when the xfrm_policy is allocated. | 991 | * field is initialized to NULL when the xfrm_policy is allocated. |
999 | * Return 0 if operation was successful (memory to allocate, legal context) | 992 | * Return 0 if operation was successful (memory to allocate, legal context) |
1000 | * @xfrm_policy_clone_security: | 993 | * @xfrm_policy_clone_security: |
1001 | * @old_ctx contains an existing xfrm_sec_ctx. | 994 | * @old_ctx contains an existing xfrm_sec_ctx. |
1002 | * @new_ctxp contains a new xfrm_sec_ctx being cloned from old. | 995 | * @new_ctxp contains a new xfrm_sec_ctx being cloned from old. |
1003 | * Allocate a security structure in new_ctxp that contains the | 996 | * Allocate a security structure in new_ctxp that contains the |
1004 | * information from the old_ctx structure. | 997 | * information from the old_ctx structure. |
1005 | * Return 0 if operation was successful (memory to allocate). | 998 | * Return 0 if operation was successful (memory to allocate). |
1006 | * @xfrm_policy_free_security: | 999 | * @xfrm_policy_free_security: |
1007 | * @ctx contains the xfrm_sec_ctx | 1000 | * @ctx contains the xfrm_sec_ctx |
1008 | * Deallocate xp->security. | 1001 | * Deallocate xp->security. |
1009 | * @xfrm_policy_delete_security: | 1002 | * @xfrm_policy_delete_security: |
1010 | * @ctx contains the xfrm_sec_ctx. | 1003 | * @ctx contains the xfrm_sec_ctx. |
1011 | * Authorize deletion of xp->security. | 1004 | * Authorize deletion of xp->security. |
1012 | * @xfrm_state_alloc_security: | 1005 | * @xfrm_state_alloc_security: |
1013 | * @x contains the xfrm_state being added to the Security Association | 1006 | * @x contains the xfrm_state being added to the Security Association |
1014 | * Database by the XFRM system. | 1007 | * Database by the XFRM system. |
1015 | * @sec_ctx contains the security context information being provided by | 1008 | * @sec_ctx contains the security context information being provided by |
1016 | * the user-level SA generation program (e.g., setkey or racoon). | 1009 | * the user-level SA generation program (e.g., setkey or racoon). |
1017 | * @secid contains the secid from which to take the mls portion of the context. | 1010 | * @secid contains the secid from which to take the mls portion of the context. |
1018 | * Allocate a security structure to the x->security field; the security | 1011 | * Allocate a security structure to the x->security field; the security |
1019 | * field is initialized to NULL when the xfrm_state is allocated. Set the | 1012 | * field is initialized to NULL when the xfrm_state is allocated. Set the |
1020 | * context to correspond to either sec_ctx or polsec, with the mls portion | 1013 | * context to correspond to either sec_ctx or polsec, with the mls portion |
1021 | * taken from secid in the latter case. | 1014 | * taken from secid in the latter case. |
1022 | * Return 0 if operation was successful (memory to allocate, legal context). | 1015 | * Return 0 if operation was successful (memory to allocate, legal context). |
1023 | * @xfrm_state_free_security: | 1016 | * @xfrm_state_free_security: |
1024 | * @x contains the xfrm_state. | 1017 | * @x contains the xfrm_state. |
1025 | * Deallocate x->security. | 1018 | * Deallocate x->security. |
1026 | * @xfrm_state_delete_security: | 1019 | * @xfrm_state_delete_security: |
1027 | * @x contains the xfrm_state. | 1020 | * @x contains the xfrm_state. |
1028 | * Authorize deletion of x->security. | 1021 | * Authorize deletion of x->security. |
1029 | * @xfrm_policy_lookup: | 1022 | * @xfrm_policy_lookup: |
1030 | * @ctx contains the xfrm_sec_ctx for which the access control is being | 1023 | * @ctx contains the xfrm_sec_ctx for which the access control is being |
1031 | * checked. | 1024 | * checked. |
1032 | * @fl_secid contains the flow security label that is used to authorize | 1025 | * @fl_secid contains the flow security label that is used to authorize |
1033 | * access to the policy xp. | 1026 | * access to the policy xp. |
1034 | * @dir contains the direction of the flow (input or output). | 1027 | * @dir contains the direction of the flow (input or output). |
1035 | * Check permission when a flow selects a xfrm_policy for processing | 1028 | * Check permission when a flow selects a xfrm_policy for processing |
1036 | * XFRMs on a packet. The hook is called when selecting either a | 1029 | * XFRMs on a packet. The hook is called when selecting either a |
1037 | * per-socket policy or a generic xfrm policy. | 1030 | * per-socket policy or a generic xfrm policy. |
1038 | * Return 0 if permission is granted, -ESRCH otherwise, or -errno | 1031 | * Return 0 if permission is granted, -ESRCH otherwise, or -errno |
1039 | * on other errors. | 1032 | * on other errors. |
1040 | * @xfrm_state_pol_flow_match: | 1033 | * @xfrm_state_pol_flow_match: |
1041 | * @x contains the state to match. | 1034 | * @x contains the state to match. |
1042 | * @xp contains the policy to check for a match. | 1035 | * @xp contains the policy to check for a match. |
1043 | * @fl contains the flow to check for a match. | 1036 | * @fl contains the flow to check for a match. |
1044 | * Return 1 if there is a match. | 1037 | * Return 1 if there is a match. |
1045 | * @xfrm_decode_session: | 1038 | * @xfrm_decode_session: |
1046 | * @skb points to skb to decode. | 1039 | * @skb points to skb to decode. |
1047 | * @secid points to the flow key secid to set. | 1040 | * @secid points to the flow key secid to set. |
1048 | * @ckall says if all xfrms used should be checked for same secid. | 1041 | * @ckall says if all xfrms used should be checked for same secid. |
1049 | * Return 0 if ckall is zero or all xfrms used have the same secid. | 1042 | * Return 0 if ckall is zero or all xfrms used have the same secid. |
1050 | * | 1043 | * |
1051 | * Security hooks affecting all Key Management operations | 1044 | * Security hooks affecting all Key Management operations |
1052 | * | 1045 | * |
1053 | * @key_alloc: | 1046 | * @key_alloc: |
1054 | * Permit allocation of a key and assign security data. Note that key does | 1047 | * Permit allocation of a key and assign security data. Note that key does |
1055 | * not have a serial number assigned at this point. | 1048 | * not have a serial number assigned at this point. |
1056 | * @key points to the key. | 1049 | * @key points to the key. |
1057 | * @flags is the allocation flags | 1050 | * @flags is the allocation flags |
1058 | * Return 0 if permission is granted, -ve error otherwise. | 1051 | * Return 0 if permission is granted, -ve error otherwise. |
1059 | * @key_free: | 1052 | * @key_free: |
1060 | * Notification of destruction; free security data. | 1053 | * Notification of destruction; free security data. |
1061 | * @key points to the key. | 1054 | * @key points to the key. |
1062 | * No return value. | 1055 | * No return value. |
1063 | * @key_permission: | 1056 | * @key_permission: |
1064 | * See whether a specific operational right is granted to a process on a | 1057 | * See whether a specific operational right is granted to a process on a |
1065 | * key. | 1058 | * key. |
1066 | * @key_ref refers to the key (key pointer + possession attribute bit). | 1059 | * @key_ref refers to the key (key pointer + possession attribute bit). |
1067 | * @cred points to the credentials to provide the context against which to | 1060 | * @cred points to the credentials to provide the context against which to |
1068 | * evaluate the security data on the key. | 1061 | * evaluate the security data on the key. |
1069 | * @perm describes the combination of permissions required of this key. | 1062 | * @perm describes the combination of permissions required of this key. |
1070 | * Return 0 if permission is granted, -ve error otherwise. | 1063 | * Return 0 if permission is granted, -ve error otherwise. |
1071 | * @key_getsecurity: | 1064 | * @key_getsecurity: |
1072 | * Get a textual representation of the security context attached to a key | 1065 | * Get a textual representation of the security context attached to a key |
1073 | * for the purposes of honouring KEYCTL_GETSECURITY. This function | 1066 | * for the purposes of honouring KEYCTL_GETSECURITY. This function |
1074 | * allocates the storage for the NUL-terminated string and the caller | 1067 | * allocates the storage for the NUL-terminated string and the caller |
1075 | * should free it. | 1068 | * should free it. |
1076 | * @key points to the key to be queried. | 1069 | * @key points to the key to be queried. |
1077 | * @_buffer points to a pointer that should be set to point to the | 1070 | * @_buffer points to a pointer that should be set to point to the |
1078 | * resulting string (if no label or an error occurs). | 1071 | * resulting string (if no label or an error occurs). |
1079 | * Return the length of the string (including terminating NUL) or -ve if | 1072 | * Return the length of the string (including terminating NUL) or -ve if |
1080 | * an error. | 1073 | * an error. |
1081 | * May also return 0 (and a NULL buffer pointer) if there is no label. | 1074 | * May also return 0 (and a NULL buffer pointer) if there is no label. |
1082 | * | 1075 | * |
1083 | * Security hooks affecting all System V IPC operations. | 1076 | * Security hooks affecting all System V IPC operations. |
1084 | * | 1077 | * |
1085 | * @ipc_permission: | 1078 | * @ipc_permission: |
1086 | * Check permissions for access to IPC | 1079 | * Check permissions for access to IPC |
1087 | * @ipcp contains the kernel IPC permission structure | 1080 | * @ipcp contains the kernel IPC permission structure |
1088 | * @flag contains the desired (requested) permission set | 1081 | * @flag contains the desired (requested) permission set |
1089 | * Return 0 if permission is granted. | 1082 | * Return 0 if permission is granted. |
1090 | * @ipc_getsecid: | 1083 | * @ipc_getsecid: |
1091 | * Get the secid associated with the ipc object. | 1084 | * Get the secid associated with the ipc object. |
1092 | * @ipcp contains the kernel IPC permission structure. | 1085 | * @ipcp contains the kernel IPC permission structure. |
1093 | * @secid contains a pointer to the location where result will be saved. | 1086 | * @secid contains a pointer to the location where result will be saved. |
1094 | * In case of failure, @secid will be set to zero. | 1087 | * In case of failure, @secid will be set to zero. |
1095 | * | 1088 | * |
1096 | * Security hooks for individual messages held in System V IPC message queues | 1089 | * Security hooks for individual messages held in System V IPC message queues |
1097 | * @msg_msg_alloc_security: | 1090 | * @msg_msg_alloc_security: |
1098 | * Allocate and attach a security structure to the msg->security field. | 1091 | * Allocate and attach a security structure to the msg->security field. |
1099 | * The security field is initialized to NULL when the structure is first | 1092 | * The security field is initialized to NULL when the structure is first |
1100 | * created. | 1093 | * created. |
1101 | * @msg contains the message structure to be modified. | 1094 | * @msg contains the message structure to be modified. |
1102 | * Return 0 if operation was successful and permission is granted. | 1095 | * Return 0 if operation was successful and permission is granted. |
1103 | * @msg_msg_free_security: | 1096 | * @msg_msg_free_security: |
1104 | * Deallocate the security structure for this message. | 1097 | * Deallocate the security structure for this message. |
1105 | * @msg contains the message structure to be modified. | 1098 | * @msg contains the message structure to be modified. |
1106 | * | 1099 | * |
1107 | * Security hooks for System V IPC Message Queues | 1100 | * Security hooks for System V IPC Message Queues |
1108 | * | 1101 | * |
1109 | * @msg_queue_alloc_security: | 1102 | * @msg_queue_alloc_security: |
1110 | * Allocate and attach a security structure to the | 1103 | * Allocate and attach a security structure to the |
1111 | * msq->q_perm.security field. The security field is initialized to | 1104 | * msq->q_perm.security field. The security field is initialized to |
1112 | * NULL when the structure is first created. | 1105 | * NULL when the structure is first created. |
1113 | * @msq contains the message queue structure to be modified. | 1106 | * @msq contains the message queue structure to be modified. |
1114 | * Return 0 if operation was successful and permission is granted. | 1107 | * Return 0 if operation was successful and permission is granted. |
1115 | * @msg_queue_free_security: | 1108 | * @msg_queue_free_security: |
1116 | * Deallocate security structure for this message queue. | 1109 | * Deallocate security structure for this message queue. |
1117 | * @msq contains the message queue structure to be modified. | 1110 | * @msq contains the message queue structure to be modified. |
1118 | * @msg_queue_associate: | 1111 | * @msg_queue_associate: |
1119 | * Check permission when a message queue is requested through the | 1112 | * Check permission when a message queue is requested through the |
1120 | * msgget system call. This hook is only called when returning the | 1113 | * msgget system call. This hook is only called when returning the |
1121 | * message queue identifier for an existing message queue, not when a | 1114 | * message queue identifier for an existing message queue, not when a |
1122 | * new message queue is created. | 1115 | * new message queue is created. |
1123 | * @msq contains the message queue to act upon. | 1116 | * @msq contains the message queue to act upon. |
1124 | * @msqflg contains the operation control flags. | 1117 | * @msqflg contains the operation control flags. |
1125 | * Return 0 if permission is granted. | 1118 | * Return 0 if permission is granted. |
1126 | * @msg_queue_msgctl: | 1119 | * @msg_queue_msgctl: |
1127 | * Check permission when a message control operation specified by @cmd | 1120 | * Check permission when a message control operation specified by @cmd |
1128 | * is to be performed on the message queue @msq. | 1121 | * is to be performed on the message queue @msq. |
1129 | * The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO. | 1122 | * The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO. |
1130 | * @msq contains the message queue to act upon. May be NULL. | 1123 | * @msq contains the message queue to act upon. May be NULL. |
1131 | * @cmd contains the operation to be performed. | 1124 | * @cmd contains the operation to be performed. |
1132 | * Return 0 if permission is granted. | 1125 | * Return 0 if permission is granted. |
1133 | * @msg_queue_msgsnd: | 1126 | * @msg_queue_msgsnd: |
1134 | * Check permission before a message, @msg, is enqueued on the message | 1127 | * Check permission before a message, @msg, is enqueued on the message |
1135 | * queue, @msq. | 1128 | * queue, @msq. |
1136 | * @msq contains the message queue to send message to. | 1129 | * @msq contains the message queue to send message to. |
1137 | * @msg contains the message to be enqueued. | 1130 | * @msg contains the message to be enqueued. |
1138 | * @msqflg contains operational flags. | 1131 | * @msqflg contains operational flags. |
1139 | * Return 0 if permission is granted. | 1132 | * Return 0 if permission is granted. |
1140 | * @msg_queue_msgrcv: | 1133 | * @msg_queue_msgrcv: |
1141 | * Check permission before a message, @msg, is removed from the message | 1134 | * Check permission before a message, @msg, is removed from the message |
1142 | * queue, @msq. The @target task structure contains a pointer to the | 1135 | * queue, @msq. The @target task structure contains a pointer to the |
1143 | * process that will be receiving the message (not equal to the current | 1136 | * process that will be receiving the message (not equal to the current |
1144 | * process when inline receives are being performed). | 1137 | * process when inline receives are being performed). |
1145 | * @msq contains the message queue to retrieve message from. | 1138 | * @msq contains the message queue to retrieve message from. |
1146 | * @msg contains the message destination. | 1139 | * @msg contains the message destination. |
1147 | * @target contains the task structure for recipient process. | 1140 | * @target contains the task structure for recipient process. |
1148 | * @type contains the type of message requested. | 1141 | * @type contains the type of message requested. |
1149 | * @mode contains the operational flags. | 1142 | * @mode contains the operational flags. |
1150 | * Return 0 if permission is granted. | 1143 | * Return 0 if permission is granted. |
1151 | * | 1144 | * |
1152 | * Security hooks for System V Shared Memory Segments | 1145 | * Security hooks for System V Shared Memory Segments |
1153 | * | 1146 | * |
1154 | * @shm_alloc_security: | 1147 | * @shm_alloc_security: |
1155 | * Allocate and attach a security structure to the shp->shm_perm.security | 1148 | * Allocate and attach a security structure to the shp->shm_perm.security |
1156 | * field. The security field is initialized to NULL when the structure is | 1149 | * field. The security field is initialized to NULL when the structure is |
1157 | * first created. | 1150 | * first created. |
1158 | * @shp contains the shared memory structure to be modified. | 1151 | * @shp contains the shared memory structure to be modified. |
1159 | * Return 0 if operation was successful and permission is granted. | 1152 | * Return 0 if operation was successful and permission is granted. |
1160 | * @shm_free_security: | 1153 | * @shm_free_security: |
1161 | * Deallocate the security struct for this memory segment. | 1154 | * Deallocate the security struct for this memory segment. |
1162 | * @shp contains the shared memory structure to be modified. | 1155 | * @shp contains the shared memory structure to be modified. |
1163 | * @shm_associate: | 1156 | * @shm_associate: |
1164 | * Check permission when a shared memory region is requested through the | 1157 | * Check permission when a shared memory region is requested through the |
1165 | * shmget system call. This hook is only called when returning the shared | 1158 | * shmget system call. This hook is only called when returning the shared |
1166 | * memory region identifier for an existing region, not when a new shared | 1159 | * memory region identifier for an existing region, not when a new shared |
1167 | * memory region is created. | 1160 | * memory region is created. |
1168 | * @shp contains the shared memory structure to be modified. | 1161 | * @shp contains the shared memory structure to be modified. |
1169 | * @shmflg contains the operation control flags. | 1162 | * @shmflg contains the operation control flags. |
1170 | * Return 0 if permission is granted. | 1163 | * Return 0 if permission is granted. |
1171 | * @shm_shmctl: | 1164 | * @shm_shmctl: |
1172 | * Check permission when a shared memory control operation specified by | 1165 | * Check permission when a shared memory control operation specified by |
1173 | * @cmd is to be performed on the shared memory region @shp. | 1166 | * @cmd is to be performed on the shared memory region @shp. |
1174 | * The @shp may be NULL, e.g. for IPC_INFO or SHM_INFO. | 1167 | * The @shp may be NULL, e.g. for IPC_INFO or SHM_INFO. |
1175 | * @shp contains shared memory structure to be modified. | 1168 | * @shp contains shared memory structure to be modified. |
1176 | * @cmd contains the operation to be performed. | 1169 | * @cmd contains the operation to be performed. |
1177 | * Return 0 if permission is granted. | 1170 | * Return 0 if permission is granted. |
1178 | * @shm_shmat: | 1171 | * @shm_shmat: |
1179 | * Check permissions prior to allowing the shmat system call to attach the | 1172 | * Check permissions prior to allowing the shmat system call to attach the |
1180 | * shared memory segment @shp to the data segment of the calling process. | 1173 | * shared memory segment @shp to the data segment of the calling process. |
1181 | * The attaching address is specified by @shmaddr. | 1174 | * The attaching address is specified by @shmaddr. |
1182 | * @shp contains the shared memory structure to be modified. | 1175 | * @shp contains the shared memory structure to be modified. |
1183 | * @shmaddr contains the address to attach memory region to. | 1176 | * @shmaddr contains the address to attach memory region to. |
1184 | * @shmflg contains the operational flags. | 1177 | * @shmflg contains the operational flags. |
1185 | * Return 0 if permission is granted. | 1178 | * Return 0 if permission is granted. |
1186 | * | 1179 | * |
1187 | * Security hooks for System V Semaphores | 1180 | * Security hooks for System V Semaphores |
1188 | * | 1181 | * |
1189 | * @sem_alloc_security: | 1182 | * @sem_alloc_security: |
1190 | * Allocate and attach a security structure to the sma->sem_perm.security | 1183 | * Allocate and attach a security structure to the sma->sem_perm.security |
1191 | * field. The security field is initialized to NULL when the structure is | 1184 | * field. The security field is initialized to NULL when the structure is |
1192 | * first created. | 1185 | * first created. |
1193 | * @sma contains the semaphore structure | 1186 | * @sma contains the semaphore structure |
1194 | * Return 0 if operation was successful and permission is granted. | 1187 | * Return 0 if operation was successful and permission is granted. |
1195 | * @sem_free_security: | 1188 | * @sem_free_security: |
1196 | * deallocate security struct for this semaphore | 1189 | * deallocate security struct for this semaphore |
1197 | * @sma contains the semaphore structure. | 1190 | * @sma contains the semaphore structure. |
1198 | * @sem_associate: | 1191 | * @sem_associate: |
1199 | * Check permission when a semaphore is requested through the semget | 1192 | * Check permission when a semaphore is requested through the semget |
1200 | * system call. This hook is only called when returning the semaphore | 1193 | * system call. This hook is only called when returning the semaphore |
1201 | * identifier for an existing semaphore, not when a new one must be | 1194 | * identifier for an existing semaphore, not when a new one must be |
1202 | * created. | 1195 | * created. |
1203 | * @sma contains the semaphore structure. | 1196 | * @sma contains the semaphore structure. |
1204 | * @semflg contains the operation control flags. | 1197 | * @semflg contains the operation control flags. |
1205 | * Return 0 if permission is granted. | 1198 | * Return 0 if permission is granted. |
1206 | * @sem_semctl: | 1199 | * @sem_semctl: |
1207 | * Check permission when a semaphore operation specified by @cmd is to be | 1200 | * Check permission when a semaphore operation specified by @cmd is to be |
1208 | * performed on the semaphore @sma. The @sma may be NULL, e.g. for | 1201 | * performed on the semaphore @sma. The @sma may be NULL, e.g. for |
1209 | * IPC_INFO or SEM_INFO. | 1202 | * IPC_INFO or SEM_INFO. |
1210 | * @sma contains the semaphore structure. May be NULL. | 1203 | * @sma contains the semaphore structure. May be NULL. |
1211 | * @cmd contains the operation to be performed. | 1204 | * @cmd contains the operation to be performed. |
1212 | * Return 0 if permission is granted. | 1205 | * Return 0 if permission is granted. |
1213 | * @sem_semop | 1206 | * @sem_semop |
1214 | * Check permissions before performing operations on members of the | 1207 | * Check permissions before performing operations on members of the |
1215 | * semaphore set @sma. If the @alter flag is nonzero, the semaphore set | 1208 | * semaphore set @sma. If the @alter flag is nonzero, the semaphore set |
1216 | * may be modified. | 1209 | * may be modified. |
1217 | * @sma contains the semaphore structure. | 1210 | * @sma contains the semaphore structure. |
1218 | * @sops contains the operations to perform. | 1211 | * @sops contains the operations to perform. |
1219 | * @nsops contains the number of operations to perform. | 1212 | * @nsops contains the number of operations to perform. |
1220 | * @alter contains the flag indicating whether changes are to be made. | 1213 | * @alter contains the flag indicating whether changes are to be made. |
1221 | * Return 0 if permission is granted. | 1214 | * Return 0 if permission is granted. |
1222 | * | 1215 | * |
1223 | * @ptrace_access_check: | 1216 | * @ptrace_access_check: |
1224 | * Check permission before allowing the current process to trace the | 1217 | * Check permission before allowing the current process to trace the |
1225 | * @child process. | 1218 | * @child process. |
1226 | * Security modules may also want to perform a process tracing check | 1219 | * Security modules may also want to perform a process tracing check |
1227 | * during an execve in the set_security or apply_creds hooks of | 1220 | * during an execve in the set_security or apply_creds hooks of |
1228 | * tracing check during an execve in the bprm_set_creds hook of | 1221 | * tracing check during an execve in the bprm_set_creds hook of |
1229 | * binprm_security_ops if the process is being traced and its security | 1222 | * binprm_security_ops if the process is being traced and its security |
1230 | * attributes would be changed by the execve. | 1223 | * attributes would be changed by the execve. |
1231 | * @child contains the task_struct structure for the target process. | 1224 | * @child contains the task_struct structure for the target process. |
1232 | * @mode contains the PTRACE_MODE flags indicating the form of access. | 1225 | * @mode contains the PTRACE_MODE flags indicating the form of access. |
1233 | * Return 0 if permission is granted. | 1226 | * Return 0 if permission is granted. |
1234 | * @ptrace_traceme: | 1227 | * @ptrace_traceme: |
1235 | * Check that the @parent process has sufficient permission to trace the | 1228 | * Check that the @parent process has sufficient permission to trace the |
1236 | * current process before allowing the current process to present itself | 1229 | * current process before allowing the current process to present itself |
1237 | * to the @parent process for tracing. | 1230 | * to the @parent process for tracing. |
1238 | * The parent process will still have to undergo the ptrace_access_check | 1231 | * The parent process will still have to undergo the ptrace_access_check |
1239 | * checks before it is allowed to trace this one. | 1232 | * checks before it is allowed to trace this one. |
1240 | * @parent contains the task_struct structure for debugger process. | 1233 | * @parent contains the task_struct structure for debugger process. |
1241 | * Return 0 if permission is granted. | 1234 | * Return 0 if permission is granted. |
1242 | * @capget: | 1235 | * @capget: |
1243 | * Get the @effective, @inheritable, and @permitted capability sets for | 1236 | * Get the @effective, @inheritable, and @permitted capability sets for |
1244 | * the @target process. The hook may also perform permission checking to | 1237 | * the @target process. The hook may also perform permission checking to |
1245 | * determine if the current process is allowed to see the capability sets | 1238 | * determine if the current process is allowed to see the capability sets |
1246 | * of the @target process. | 1239 | * of the @target process. |
1247 | * @target contains the task_struct structure for target process. | 1240 | * @target contains the task_struct structure for target process. |
1248 | * @effective contains the effective capability set. | 1241 | * @effective contains the effective capability set. |
1249 | * @inheritable contains the inheritable capability set. | 1242 | * @inheritable contains the inheritable capability set. |
1250 | * @permitted contains the permitted capability set. | 1243 | * @permitted contains the permitted capability set. |
1251 | * Return 0 if the capability sets were successfully obtained. | 1244 | * Return 0 if the capability sets were successfully obtained. |
1252 | * @capset: | 1245 | * @capset: |
1253 | * Set the @effective, @inheritable, and @permitted capability sets for | 1246 | * Set the @effective, @inheritable, and @permitted capability sets for |
1254 | * the current process. | 1247 | * the current process. |
1255 | * @new contains the new credentials structure for target process. | 1248 | * @new contains the new credentials structure for target process. |
1256 | * @old contains the current credentials structure for target process. | 1249 | * @old contains the current credentials structure for target process. |
1257 | * @effective contains the effective capability set. | 1250 | * @effective contains the effective capability set. |
1258 | * @inheritable contains the inheritable capability set. | 1251 | * @inheritable contains the inheritable capability set. |
1259 | * @permitted contains the permitted capability set. | 1252 | * @permitted contains the permitted capability set. |
1260 | * Return 0 and update @new if permission is granted. | 1253 | * Return 0 and update @new if permission is granted. |
1261 | * @capable: | 1254 | * @capable: |
1262 | * Check whether the @tsk process has the @cap capability in the indicated | 1255 | * Check whether the @tsk process has the @cap capability in the indicated |
1263 | * credentials. | 1256 | * credentials. |
1264 | * @cred contains the credentials to use. | 1257 | * @cred contains the credentials to use. |
1265 | * @ns contains the user namespace we want the capability in | 1258 | * @ns contains the user namespace we want the capability in |
1266 | * @cap contains the capability <include/linux/capability.h>. | 1259 | * @cap contains the capability <include/linux/capability.h>. |
1267 | * @audit: Whether to write an audit message or not | 1260 | * @audit: Whether to write an audit message or not |
1268 | * Return 0 if the capability is granted for @tsk. | 1261 | * Return 0 if the capability is granted for @tsk. |
1269 | * @syslog: | 1262 | * @syslog: |
1270 | * Check permission before accessing the kernel message ring or changing | 1263 | * Check permission before accessing the kernel message ring or changing |
1271 | * logging to the console. | 1264 | * logging to the console. |
1272 | * See the syslog(2) manual page for an explanation of the @type values. | 1265 | * See the syslog(2) manual page for an explanation of the @type values. |
1273 | * @type contains the type of action. | 1266 | * @type contains the type of action. |
1274 | * @from_file indicates the context of action (if it came from /proc). | 1267 | * @from_file indicates the context of action (if it came from /proc). |
1275 | * Return 0 if permission is granted. | 1268 | * Return 0 if permission is granted. |
1276 | * @settime: | 1269 | * @settime: |
1277 | * Check permission to change the system time. | 1270 | * Check permission to change the system time. |
1278 | * struct timespec and timezone are defined in include/linux/time.h | 1271 | * struct timespec and timezone are defined in include/linux/time.h |
1279 | * @ts contains new time | 1272 | * @ts contains new time |
1280 | * @tz contains new timezone | 1273 | * @tz contains new timezone |
1281 | * Return 0 if permission is granted. | 1274 | * Return 0 if permission is granted. |
1282 | * @vm_enough_memory: | 1275 | * @vm_enough_memory: |
1283 | * Check permissions for allocating a new virtual mapping. | 1276 | * Check permissions for allocating a new virtual mapping. |
1284 | * @mm contains the mm struct it is being added to. | 1277 | * @mm contains the mm struct it is being added to. |
1285 | * @pages contains the number of pages. | 1278 | * @pages contains the number of pages. |
1286 | * Return 0 if permission is granted. | 1279 | * Return 0 if permission is granted. |
1287 | * | 1280 | * |
1288 | * @secid_to_secctx: | 1281 | * @secid_to_secctx: |
1289 | * Convert secid to security context. If secdata is NULL the length of | 1282 | * Convert secid to security context. If secdata is NULL the length of |
1290 | * the result will be returned in seclen, but no secdata will be returned. | 1283 | * the result will be returned in seclen, but no secdata will be returned. |
1291 | * This does mean that the length could change between calls to check the | 1284 | * This does mean that the length could change between calls to check the |
1292 | * length and the next call which actually allocates and returns the secdata. | 1285 | * length and the next call which actually allocates and returns the secdata. |
1293 | * @secid contains the security ID. | 1286 | * @secid contains the security ID. |
1294 | * @secdata contains the pointer that stores the converted security context. | 1287 | * @secdata contains the pointer that stores the converted security context. |
1295 | * @seclen pointer which contains the length of the data | 1288 | * @seclen pointer which contains the length of the data |
1296 | * @secctx_to_secid: | 1289 | * @secctx_to_secid: |
1297 | * Convert security context to secid. | 1290 | * Convert security context to secid. |
1298 | * @secid contains the pointer to the generated security ID. | 1291 | * @secid contains the pointer to the generated security ID. |
1299 | * @secdata contains the security context. | 1292 | * @secdata contains the security context. |
1300 | * | 1293 | * |
1301 | * @release_secctx: | 1294 | * @release_secctx: |
1302 | * Release the security context. | 1295 | * Release the security context. |
1303 | * @secdata contains the security context. | 1296 | * @secdata contains the security context. |
1304 | * @seclen contains the length of the security context. | 1297 | * @seclen contains the length of the security context. |
1305 | * | 1298 | * |
1306 | * Security hooks for Audit | 1299 | * Security hooks for Audit |
1307 | * | 1300 | * |
1308 | * @audit_rule_init: | 1301 | * @audit_rule_init: |
1309 | * Allocate and initialize an LSM audit rule structure. | 1302 | * Allocate and initialize an LSM audit rule structure. |
1310 | * @field contains the required Audit action. Fields flags are defined in include/linux/audit.h | 1303 | * @field contains the required Audit action. Fields flags are defined in include/linux/audit.h |
1311 | * @op contains the operator the rule uses. | 1304 | * @op contains the operator the rule uses. |
1312 | * @rulestr contains the context where the rule will be applied to. | 1305 | * @rulestr contains the context where the rule will be applied to. |
1313 | * @lsmrule contains a pointer to receive the result. | 1306 | * @lsmrule contains a pointer to receive the result. |
1314 | * Return 0 if @lsmrule has been successfully set, | 1307 | * Return 0 if @lsmrule has been successfully set, |
1315 | * -EINVAL in case of an invalid rule. | 1308 | * -EINVAL in case of an invalid rule. |
1316 | * | 1309 | * |
1317 | * @audit_rule_known: | 1310 | * @audit_rule_known: |
1318 | * Specifies whether given @rule contains any fields related to current LSM. | 1311 | * Specifies whether given @rule contains any fields related to current LSM. |
1319 | * @rule contains the audit rule of interest. | 1312 | * @rule contains the audit rule of interest. |
1320 | * Return 1 in case of relation found, 0 otherwise. | 1313 | * Return 1 in case of relation found, 0 otherwise. |
1321 | * | 1314 | * |
1322 | * @audit_rule_match: | 1315 | * @audit_rule_match: |
1323 | * Determine if given @secid matches a rule previously approved | 1316 | * Determine if given @secid matches a rule previously approved |
1324 | * by @audit_rule_known. | 1317 | * by @audit_rule_known. |
1325 | * @secid contains the security id in question. | 1318 | * @secid contains the security id in question. |
1326 | * @field contains the field which relates to current LSM. | 1319 | * @field contains the field which relates to current LSM. |
1327 | * @op contains the operator that will be used for matching. | 1320 | * @op contains the operator that will be used for matching. |
1328 | * @rule points to the audit rule that will be checked against. | 1321 | * @rule points to the audit rule that will be checked against. |
1329 | * @actx points to the audit context associated with the check. | 1322 | * @actx points to the audit context associated with the check. |
1330 | * Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure. | 1323 | * Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure. |
1331 | * | 1324 | * |
1332 | * @audit_rule_free: | 1325 | * @audit_rule_free: |
1333 | * Deallocate the LSM audit rule structure previously allocated by | 1326 | * Deallocate the LSM audit rule structure previously allocated by |
1334 | * audit_rule_init. | 1327 | * audit_rule_init. |
1335 | * @rule contains the allocated rule | 1328 | * @rule contains the allocated rule |
1336 | * | 1329 | * |
1337 | * @inode_notifysecctx: | 1330 | * @inode_notifysecctx: |
1338 | * Notify the security module of what the security context of an inode | 1331 | * Notify the security module of what the security context of an inode |
1339 | * should be. Initializes the incore security context managed by the | 1332 | * should be. Initializes the incore security context managed by the |
1340 | * security module for this inode. Example usage: NFS client invokes | 1333 | * security module for this inode. Example usage: NFS client invokes |
1341 | * this hook to initialize the security context in its incore inode to the | 1334 | * this hook to initialize the security context in its incore inode to the |
1342 | * value provided by the server for the file when the server returned the | 1335 | * value provided by the server for the file when the server returned the |
1343 | * file's attributes to the client. | 1336 | * file's attributes to the client. |
1344 | * | 1337 | * |
1345 | * Must be called with inode->i_mutex locked. | 1338 | * Must be called with inode->i_mutex locked. |
1346 | * | 1339 | * |
1347 | * @inode we wish to set the security context of. | 1340 | * @inode we wish to set the security context of. |
1348 | * @ctx contains the string which we wish to set in the inode. | 1341 | * @ctx contains the string which we wish to set in the inode. |
1349 | * @ctxlen contains the length of @ctx. | 1342 | * @ctxlen contains the length of @ctx. |
1350 | * | 1343 | * |
1351 | * @inode_setsecctx: | 1344 | * @inode_setsecctx: |
1352 | * Change the security context of an inode. Updates the | 1345 | * Change the security context of an inode. Updates the |
1353 | * incore security context managed by the security module and invokes the | 1346 | * incore security context managed by the security module and invokes the |
1354 | * fs code as needed (via __vfs_setxattr_noperm) to update any backing | 1347 | * fs code as needed (via __vfs_setxattr_noperm) to update any backing |
1355 | * xattrs that represent the context. Example usage: NFS server invokes | 1348 | * xattrs that represent the context. Example usage: NFS server invokes |
1356 | * this hook to change the security context in its incore inode and on the | 1349 | * this hook to change the security context in its incore inode and on the |
1357 | * backing filesystem to a value provided by the client on a SETATTR | 1350 | * backing filesystem to a value provided by the client on a SETATTR |
1358 | * operation. | 1351 | * operation. |
1359 | * | 1352 | * |
1360 | * Must be called with inode->i_mutex locked. | 1353 | * Must be called with inode->i_mutex locked. |
1361 | * | 1354 | * |
1362 | * @dentry contains the inode we wish to set the security context of. | 1355 | * @dentry contains the inode we wish to set the security context of. |
1363 | * @ctx contains the string which we wish to set in the inode. | 1356 | * @ctx contains the string which we wish to set in the inode. |
1364 | * @ctxlen contains the length of @ctx. | 1357 | * @ctxlen contains the length of @ctx. |
1365 | * | 1358 | * |
1366 | * @inode_getsecctx: | 1359 | * @inode_getsecctx: |
1367 | * Returns a string containing all relavent security context information | 1360 | * Returns a string containing all relavent security context information |
1368 | * | 1361 | * |
1369 | * @inode we wish to set the security context of. | 1362 | * @inode we wish to set the security context of. |
1370 | * @ctx is a pointer in which to place the allocated security context. | 1363 | * @ctx is a pointer in which to place the allocated security context. |
1371 | * @ctxlen points to the place to put the length of @ctx. | 1364 | * @ctxlen points to the place to put the length of @ctx. |
1372 | * This is the main security structure. | 1365 | * This is the main security structure. |
1373 | */ | 1366 | */ |
1374 | struct security_operations { | 1367 | struct security_operations { |
1375 | char name[SECURITY_NAME_MAX + 1]; | 1368 | char name[SECURITY_NAME_MAX + 1]; |
1376 | 1369 | ||
1377 | int (*ptrace_access_check) (struct task_struct *child, unsigned int mode); | 1370 | int (*ptrace_access_check) (struct task_struct *child, unsigned int mode); |
1378 | int (*ptrace_traceme) (struct task_struct *parent); | 1371 | int (*ptrace_traceme) (struct task_struct *parent); |
1379 | int (*capget) (struct task_struct *target, | 1372 | int (*capget) (struct task_struct *target, |
1380 | kernel_cap_t *effective, | 1373 | kernel_cap_t *effective, |
1381 | kernel_cap_t *inheritable, kernel_cap_t *permitted); | 1374 | kernel_cap_t *inheritable, kernel_cap_t *permitted); |
1382 | int (*capset) (struct cred *new, | 1375 | int (*capset) (struct cred *new, |
1383 | const struct cred *old, | 1376 | const struct cred *old, |
1384 | const kernel_cap_t *effective, | 1377 | const kernel_cap_t *effective, |
1385 | const kernel_cap_t *inheritable, | 1378 | const kernel_cap_t *inheritable, |
1386 | const kernel_cap_t *permitted); | 1379 | const kernel_cap_t *permitted); |
1387 | int (*capable) (const struct cred *cred, struct user_namespace *ns, | 1380 | int (*capable) (const struct cred *cred, struct user_namespace *ns, |
1388 | int cap, int audit); | 1381 | int cap, int audit); |
1389 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); | 1382 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); |
1390 | int (*quota_on) (struct dentry *dentry); | 1383 | int (*quota_on) (struct dentry *dentry); |
1391 | int (*syslog) (int type); | 1384 | int (*syslog) (int type); |
1392 | int (*settime) (const struct timespec *ts, const struct timezone *tz); | 1385 | int (*settime) (const struct timespec *ts, const struct timezone *tz); |
1393 | int (*vm_enough_memory) (struct mm_struct *mm, long pages); | 1386 | int (*vm_enough_memory) (struct mm_struct *mm, long pages); |
1394 | 1387 | ||
1395 | int (*bprm_set_creds) (struct linux_binprm *bprm); | 1388 | int (*bprm_set_creds) (struct linux_binprm *bprm); |
1396 | int (*bprm_check_security) (struct linux_binprm *bprm); | 1389 | int (*bprm_check_security) (struct linux_binprm *bprm); |
1397 | int (*bprm_secureexec) (struct linux_binprm *bprm); | 1390 | int (*bprm_secureexec) (struct linux_binprm *bprm); |
1398 | void (*bprm_committing_creds) (struct linux_binprm *bprm); | 1391 | void (*bprm_committing_creds) (struct linux_binprm *bprm); |
1399 | void (*bprm_committed_creds) (struct linux_binprm *bprm); | 1392 | void (*bprm_committed_creds) (struct linux_binprm *bprm); |
1400 | 1393 | ||
1401 | int (*sb_alloc_security) (struct super_block *sb); | 1394 | int (*sb_alloc_security) (struct super_block *sb); |
1402 | void (*sb_free_security) (struct super_block *sb); | 1395 | void (*sb_free_security) (struct super_block *sb); |
1403 | int (*sb_copy_data) (char *orig, char *copy); | 1396 | int (*sb_copy_data) (char *orig, char *copy); |
1404 | int (*sb_remount) (struct super_block *sb, void *data); | 1397 | int (*sb_remount) (struct super_block *sb, void *data); |
1405 | int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); | 1398 | int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); |
1406 | int (*sb_show_options) (struct seq_file *m, struct super_block *sb); | 1399 | int (*sb_show_options) (struct seq_file *m, struct super_block *sb); |
1407 | int (*sb_statfs) (struct dentry *dentry); | 1400 | int (*sb_statfs) (struct dentry *dentry); |
1408 | int (*sb_mount) (char *dev_name, struct path *path, | 1401 | int (*sb_mount) (char *dev_name, struct path *path, |
1409 | char *type, unsigned long flags, void *data); | 1402 | char *type, unsigned long flags, void *data); |
1410 | int (*sb_umount) (struct vfsmount *mnt, int flags); | 1403 | int (*sb_umount) (struct vfsmount *mnt, int flags); |
1411 | int (*sb_pivotroot) (struct path *old_path, | 1404 | int (*sb_pivotroot) (struct path *old_path, |
1412 | struct path *new_path); | 1405 | struct path *new_path); |
1413 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1406 | int (*sb_set_mnt_opts) (struct super_block *sb, |
1414 | struct security_mnt_opts *opts); | 1407 | struct security_mnt_opts *opts); |
1415 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, | 1408 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, |
1416 | struct super_block *newsb); | 1409 | struct super_block *newsb); |
1417 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1410 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
1418 | 1411 | ||
1419 | #ifdef CONFIG_SECURITY_PATH | 1412 | #ifdef CONFIG_SECURITY_PATH |
1420 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | 1413 | int (*path_unlink) (struct path *dir, struct dentry *dentry); |
1421 | int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); | 1414 | int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); |
1422 | int (*path_rmdir) (struct path *dir, struct dentry *dentry); | 1415 | int (*path_rmdir) (struct path *dir, struct dentry *dentry); |
1423 | int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, | 1416 | int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, |
1424 | unsigned int dev); | 1417 | unsigned int dev); |
1425 | int (*path_truncate) (struct path *path); | 1418 | int (*path_truncate) (struct path *path); |
1426 | int (*path_symlink) (struct path *dir, struct dentry *dentry, | 1419 | int (*path_symlink) (struct path *dir, struct dentry *dentry, |
1427 | const char *old_name); | 1420 | const char *old_name); |
1428 | int (*path_link) (struct dentry *old_dentry, struct path *new_dir, | 1421 | int (*path_link) (struct dentry *old_dentry, struct path *new_dir, |
1429 | struct dentry *new_dentry); | 1422 | struct dentry *new_dentry); |
1430 | int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, | 1423 | int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, |
1431 | struct path *new_dir, struct dentry *new_dentry); | 1424 | struct path *new_dir, struct dentry *new_dentry); |
1432 | int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt, | 1425 | int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt, |
1433 | mode_t mode); | 1426 | mode_t mode); |
1434 | int (*path_chown) (struct path *path, uid_t uid, gid_t gid); | 1427 | int (*path_chown) (struct path *path, uid_t uid, gid_t gid); |
1435 | int (*path_chroot) (struct path *path); | 1428 | int (*path_chroot) (struct path *path); |
1436 | #endif | 1429 | #endif |
1437 | 1430 | ||
1438 | int (*inode_alloc_security) (struct inode *inode); | 1431 | int (*inode_alloc_security) (struct inode *inode); |
1439 | void (*inode_free_security) (struct inode *inode); | 1432 | void (*inode_free_security) (struct inode *inode); |
1440 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | 1433 | int (*inode_init_security) (struct inode *inode, struct inode *dir, |
1441 | const struct qstr *qstr, char **name, | 1434 | const struct qstr *qstr, char **name, |
1442 | void **value, size_t *len); | 1435 | void **value, size_t *len); |
1443 | int (*inode_create) (struct inode *dir, | 1436 | int (*inode_create) (struct inode *dir, |
1444 | struct dentry *dentry, int mode); | 1437 | struct dentry *dentry, int mode); |
1445 | int (*inode_link) (struct dentry *old_dentry, | 1438 | int (*inode_link) (struct dentry *old_dentry, |
1446 | struct inode *dir, struct dentry *new_dentry); | 1439 | struct inode *dir, struct dentry *new_dentry); |
1447 | int (*inode_unlink) (struct inode *dir, struct dentry *dentry); | 1440 | int (*inode_unlink) (struct inode *dir, struct dentry *dentry); |
1448 | int (*inode_symlink) (struct inode *dir, | 1441 | int (*inode_symlink) (struct inode *dir, |
1449 | struct dentry *dentry, const char *old_name); | 1442 | struct dentry *dentry, const char *old_name); |
1450 | int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode); | 1443 | int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode); |
1451 | int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); | 1444 | int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); |
1452 | int (*inode_mknod) (struct inode *dir, struct dentry *dentry, | 1445 | int (*inode_mknod) (struct inode *dir, struct dentry *dentry, |
1453 | int mode, dev_t dev); | 1446 | int mode, dev_t dev); |
1454 | int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, | 1447 | int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, |
1455 | struct inode *new_dir, struct dentry *new_dentry); | 1448 | struct inode *new_dir, struct dentry *new_dentry); |
1456 | int (*inode_readlink) (struct dentry *dentry); | 1449 | int (*inode_readlink) (struct dentry *dentry); |
1457 | int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); | 1450 | int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); |
1458 | int (*inode_permission) (struct inode *inode, int mask); | 1451 | int (*inode_permission) (struct inode *inode, int mask); |
1459 | int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); | 1452 | int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); |
1460 | int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); | 1453 | int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); |
1461 | int (*inode_setxattr) (struct dentry *dentry, const char *name, | 1454 | int (*inode_setxattr) (struct dentry *dentry, const char *name, |
1462 | const void *value, size_t size, int flags); | 1455 | const void *value, size_t size, int flags); |
1463 | void (*inode_post_setxattr) (struct dentry *dentry, const char *name, | 1456 | void (*inode_post_setxattr) (struct dentry *dentry, const char *name, |
1464 | const void *value, size_t size, int flags); | 1457 | const void *value, size_t size, int flags); |
1465 | int (*inode_getxattr) (struct dentry *dentry, const char *name); | 1458 | int (*inode_getxattr) (struct dentry *dentry, const char *name); |
1466 | int (*inode_listxattr) (struct dentry *dentry); | 1459 | int (*inode_listxattr) (struct dentry *dentry); |
1467 | int (*inode_removexattr) (struct dentry *dentry, const char *name); | 1460 | int (*inode_removexattr) (struct dentry *dentry, const char *name); |
1468 | int (*inode_need_killpriv) (struct dentry *dentry); | 1461 | int (*inode_need_killpriv) (struct dentry *dentry); |
1469 | int (*inode_killpriv) (struct dentry *dentry); | 1462 | int (*inode_killpriv) (struct dentry *dentry); |
1470 | int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc); | 1463 | int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc); |
1471 | int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags); | 1464 | int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags); |
1472 | int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size); | 1465 | int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size); |
1473 | void (*inode_getsecid) (const struct inode *inode, u32 *secid); | 1466 | void (*inode_getsecid) (const struct inode *inode, u32 *secid); |
1474 | 1467 | ||
1475 | int (*file_permission) (struct file *file, int mask); | 1468 | int (*file_permission) (struct file *file, int mask); |
1476 | int (*file_alloc_security) (struct file *file); | 1469 | int (*file_alloc_security) (struct file *file); |
1477 | void (*file_free_security) (struct file *file); | 1470 | void (*file_free_security) (struct file *file); |
1478 | int (*file_ioctl) (struct file *file, unsigned int cmd, | 1471 | int (*file_ioctl) (struct file *file, unsigned int cmd, |
1479 | unsigned long arg); | 1472 | unsigned long arg); |
1480 | int (*file_mmap) (struct file *file, | 1473 | int (*file_mmap) (struct file *file, |
1481 | unsigned long reqprot, unsigned long prot, | 1474 | unsigned long reqprot, unsigned long prot, |
1482 | unsigned long flags, unsigned long addr, | 1475 | unsigned long flags, unsigned long addr, |
1483 | unsigned long addr_only); | 1476 | unsigned long addr_only); |
1484 | int (*file_mprotect) (struct vm_area_struct *vma, | 1477 | int (*file_mprotect) (struct vm_area_struct *vma, |
1485 | unsigned long reqprot, | 1478 | unsigned long reqprot, |
1486 | unsigned long prot); | 1479 | unsigned long prot); |
1487 | int (*file_lock) (struct file *file, unsigned int cmd); | 1480 | int (*file_lock) (struct file *file, unsigned int cmd); |
1488 | int (*file_fcntl) (struct file *file, unsigned int cmd, | 1481 | int (*file_fcntl) (struct file *file, unsigned int cmd, |
1489 | unsigned long arg); | 1482 | unsigned long arg); |
1490 | int (*file_set_fowner) (struct file *file); | 1483 | int (*file_set_fowner) (struct file *file); |
1491 | int (*file_send_sigiotask) (struct task_struct *tsk, | 1484 | int (*file_send_sigiotask) (struct task_struct *tsk, |
1492 | struct fown_struct *fown, int sig); | 1485 | struct fown_struct *fown, int sig); |
1493 | int (*file_receive) (struct file *file); | 1486 | int (*file_receive) (struct file *file); |
1494 | int (*dentry_open) (struct file *file, const struct cred *cred); | 1487 | int (*dentry_open) (struct file *file, const struct cred *cred); |
1495 | 1488 | ||
1496 | int (*task_create) (unsigned long clone_flags); | 1489 | int (*task_create) (unsigned long clone_flags); |
1497 | int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp); | 1490 | int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp); |
1498 | void (*cred_free) (struct cred *cred); | 1491 | void (*cred_free) (struct cred *cred); |
1499 | int (*cred_prepare)(struct cred *new, const struct cred *old, | 1492 | int (*cred_prepare)(struct cred *new, const struct cred *old, |
1500 | gfp_t gfp); | 1493 | gfp_t gfp); |
1501 | void (*cred_transfer)(struct cred *new, const struct cred *old); | 1494 | void (*cred_transfer)(struct cred *new, const struct cred *old); |
1502 | int (*kernel_act_as)(struct cred *new, u32 secid); | 1495 | int (*kernel_act_as)(struct cred *new, u32 secid); |
1503 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); | 1496 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); |
1504 | int (*kernel_module_request)(char *kmod_name); | 1497 | int (*kernel_module_request)(char *kmod_name); |
1505 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, | 1498 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, |
1506 | int flags); | 1499 | int flags); |
1507 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); | 1500 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); |
1508 | int (*task_getpgid) (struct task_struct *p); | 1501 | int (*task_getpgid) (struct task_struct *p); |
1509 | int (*task_getsid) (struct task_struct *p); | 1502 | int (*task_getsid) (struct task_struct *p); |
1510 | void (*task_getsecid) (struct task_struct *p, u32 *secid); | 1503 | void (*task_getsecid) (struct task_struct *p, u32 *secid); |
1511 | int (*task_setnice) (struct task_struct *p, int nice); | 1504 | int (*task_setnice) (struct task_struct *p, int nice); |
1512 | int (*task_setioprio) (struct task_struct *p, int ioprio); | 1505 | int (*task_setioprio) (struct task_struct *p, int ioprio); |
1513 | int (*task_getioprio) (struct task_struct *p); | 1506 | int (*task_getioprio) (struct task_struct *p); |
1514 | int (*task_setrlimit) (struct task_struct *p, unsigned int resource, | 1507 | int (*task_setrlimit) (struct task_struct *p, unsigned int resource, |
1515 | struct rlimit *new_rlim); | 1508 | struct rlimit *new_rlim); |
1516 | int (*task_setscheduler) (struct task_struct *p); | 1509 | int (*task_setscheduler) (struct task_struct *p); |
1517 | int (*task_getscheduler) (struct task_struct *p); | 1510 | int (*task_getscheduler) (struct task_struct *p); |
1518 | int (*task_movememory) (struct task_struct *p); | 1511 | int (*task_movememory) (struct task_struct *p); |
1519 | int (*task_kill) (struct task_struct *p, | 1512 | int (*task_kill) (struct task_struct *p, |
1520 | struct siginfo *info, int sig, u32 secid); | 1513 | struct siginfo *info, int sig, u32 secid); |
1521 | int (*task_wait) (struct task_struct *p); | 1514 | int (*task_wait) (struct task_struct *p); |
1522 | int (*task_prctl) (int option, unsigned long arg2, | 1515 | int (*task_prctl) (int option, unsigned long arg2, |
1523 | unsigned long arg3, unsigned long arg4, | 1516 | unsigned long arg3, unsigned long arg4, |
1524 | unsigned long arg5); | 1517 | unsigned long arg5); |
1525 | void (*task_to_inode) (struct task_struct *p, struct inode *inode); | 1518 | void (*task_to_inode) (struct task_struct *p, struct inode *inode); |
1526 | 1519 | ||
1527 | int (*ipc_permission) (struct kern_ipc_perm *ipcp, short flag); | 1520 | int (*ipc_permission) (struct kern_ipc_perm *ipcp, short flag); |
1528 | void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid); | 1521 | void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid); |
1529 | 1522 | ||
1530 | int (*msg_msg_alloc_security) (struct msg_msg *msg); | 1523 | int (*msg_msg_alloc_security) (struct msg_msg *msg); |
1531 | void (*msg_msg_free_security) (struct msg_msg *msg); | 1524 | void (*msg_msg_free_security) (struct msg_msg *msg); |
1532 | 1525 | ||
1533 | int (*msg_queue_alloc_security) (struct msg_queue *msq); | 1526 | int (*msg_queue_alloc_security) (struct msg_queue *msq); |
1534 | void (*msg_queue_free_security) (struct msg_queue *msq); | 1527 | void (*msg_queue_free_security) (struct msg_queue *msq); |
1535 | int (*msg_queue_associate) (struct msg_queue *msq, int msqflg); | 1528 | int (*msg_queue_associate) (struct msg_queue *msq, int msqflg); |
1536 | int (*msg_queue_msgctl) (struct msg_queue *msq, int cmd); | 1529 | int (*msg_queue_msgctl) (struct msg_queue *msq, int cmd); |
1537 | int (*msg_queue_msgsnd) (struct msg_queue *msq, | 1530 | int (*msg_queue_msgsnd) (struct msg_queue *msq, |
1538 | struct msg_msg *msg, int msqflg); | 1531 | struct msg_msg *msg, int msqflg); |
1539 | int (*msg_queue_msgrcv) (struct msg_queue *msq, | 1532 | int (*msg_queue_msgrcv) (struct msg_queue *msq, |
1540 | struct msg_msg *msg, | 1533 | struct msg_msg *msg, |
1541 | struct task_struct *target, | 1534 | struct task_struct *target, |
1542 | long type, int mode); | 1535 | long type, int mode); |
1543 | 1536 | ||
1544 | int (*shm_alloc_security) (struct shmid_kernel *shp); | 1537 | int (*shm_alloc_security) (struct shmid_kernel *shp); |
1545 | void (*shm_free_security) (struct shmid_kernel *shp); | 1538 | void (*shm_free_security) (struct shmid_kernel *shp); |
1546 | int (*shm_associate) (struct shmid_kernel *shp, int shmflg); | 1539 | int (*shm_associate) (struct shmid_kernel *shp, int shmflg); |
1547 | int (*shm_shmctl) (struct shmid_kernel *shp, int cmd); | 1540 | int (*shm_shmctl) (struct shmid_kernel *shp, int cmd); |
1548 | int (*shm_shmat) (struct shmid_kernel *shp, | 1541 | int (*shm_shmat) (struct shmid_kernel *shp, |
1549 | char __user *shmaddr, int shmflg); | 1542 | char __user *shmaddr, int shmflg); |
1550 | 1543 | ||
1551 | int (*sem_alloc_security) (struct sem_array *sma); | 1544 | int (*sem_alloc_security) (struct sem_array *sma); |
1552 | void (*sem_free_security) (struct sem_array *sma); | 1545 | void (*sem_free_security) (struct sem_array *sma); |
1553 | int (*sem_associate) (struct sem_array *sma, int semflg); | 1546 | int (*sem_associate) (struct sem_array *sma, int semflg); |
1554 | int (*sem_semctl) (struct sem_array *sma, int cmd); | 1547 | int (*sem_semctl) (struct sem_array *sma, int cmd); |
1555 | int (*sem_semop) (struct sem_array *sma, | 1548 | int (*sem_semop) (struct sem_array *sma, |
1556 | struct sembuf *sops, unsigned nsops, int alter); | 1549 | struct sembuf *sops, unsigned nsops, int alter); |
1557 | 1550 | ||
1558 | int (*netlink_send) (struct sock *sk, struct sk_buff *skb); | 1551 | int (*netlink_send) (struct sock *sk, struct sk_buff *skb); |
1559 | int (*netlink_recv) (struct sk_buff *skb, int cap); | ||
1560 | 1552 | ||
1561 | void (*d_instantiate) (struct dentry *dentry, struct inode *inode); | 1553 | void (*d_instantiate) (struct dentry *dentry, struct inode *inode); |
1562 | 1554 | ||
1563 | int (*getprocattr) (struct task_struct *p, char *name, char **value); | 1555 | int (*getprocattr) (struct task_struct *p, char *name, char **value); |
1564 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); | 1556 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); |
1565 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); | 1557 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); |
1566 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); | 1558 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); |
1567 | void (*release_secctx) (char *secdata, u32 seclen); | 1559 | void (*release_secctx) (char *secdata, u32 seclen); |
1568 | 1560 | ||
1569 | int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); | 1561 | int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); |
1570 | int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); | 1562 | int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); |
1571 | int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); | 1563 | int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); |
1572 | 1564 | ||
1573 | #ifdef CONFIG_SECURITY_NETWORK | 1565 | #ifdef CONFIG_SECURITY_NETWORK |
1574 | int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk); | 1566 | int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk); |
1575 | int (*unix_may_send) (struct socket *sock, struct socket *other); | 1567 | int (*unix_may_send) (struct socket *sock, struct socket *other); |
1576 | 1568 | ||
1577 | int (*socket_create) (int family, int type, int protocol, int kern); | 1569 | int (*socket_create) (int family, int type, int protocol, int kern); |
1578 | int (*socket_post_create) (struct socket *sock, int family, | 1570 | int (*socket_post_create) (struct socket *sock, int family, |
1579 | int type, int protocol, int kern); | 1571 | int type, int protocol, int kern); |
1580 | int (*socket_bind) (struct socket *sock, | 1572 | int (*socket_bind) (struct socket *sock, |
1581 | struct sockaddr *address, int addrlen); | 1573 | struct sockaddr *address, int addrlen); |
1582 | int (*socket_connect) (struct socket *sock, | 1574 | int (*socket_connect) (struct socket *sock, |
1583 | struct sockaddr *address, int addrlen); | 1575 | struct sockaddr *address, int addrlen); |
1584 | int (*socket_listen) (struct socket *sock, int backlog); | 1576 | int (*socket_listen) (struct socket *sock, int backlog); |
1585 | int (*socket_accept) (struct socket *sock, struct socket *newsock); | 1577 | int (*socket_accept) (struct socket *sock, struct socket *newsock); |
1586 | int (*socket_sendmsg) (struct socket *sock, | 1578 | int (*socket_sendmsg) (struct socket *sock, |
1587 | struct msghdr *msg, int size); | 1579 | struct msghdr *msg, int size); |
1588 | int (*socket_recvmsg) (struct socket *sock, | 1580 | int (*socket_recvmsg) (struct socket *sock, |
1589 | struct msghdr *msg, int size, int flags); | 1581 | struct msghdr *msg, int size, int flags); |
1590 | int (*socket_getsockname) (struct socket *sock); | 1582 | int (*socket_getsockname) (struct socket *sock); |
1591 | int (*socket_getpeername) (struct socket *sock); | 1583 | int (*socket_getpeername) (struct socket *sock); |
1592 | int (*socket_getsockopt) (struct socket *sock, int level, int optname); | 1584 | int (*socket_getsockopt) (struct socket *sock, int level, int optname); |
1593 | int (*socket_setsockopt) (struct socket *sock, int level, int optname); | 1585 | int (*socket_setsockopt) (struct socket *sock, int level, int optname); |
1594 | int (*socket_shutdown) (struct socket *sock, int how); | 1586 | int (*socket_shutdown) (struct socket *sock, int how); |
1595 | int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb); | 1587 | int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb); |
1596 | int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); | 1588 | int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); |
1597 | int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); | 1589 | int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); |
1598 | int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); | 1590 | int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); |
1599 | void (*sk_free_security) (struct sock *sk); | 1591 | void (*sk_free_security) (struct sock *sk); |
1600 | void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); | 1592 | void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); |
1601 | void (*sk_getsecid) (struct sock *sk, u32 *secid); | 1593 | void (*sk_getsecid) (struct sock *sk, u32 *secid); |
1602 | void (*sock_graft) (struct sock *sk, struct socket *parent); | 1594 | void (*sock_graft) (struct sock *sk, struct socket *parent); |
1603 | int (*inet_conn_request) (struct sock *sk, struct sk_buff *skb, | 1595 | int (*inet_conn_request) (struct sock *sk, struct sk_buff *skb, |
1604 | struct request_sock *req); | 1596 | struct request_sock *req); |
1605 | void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req); | 1597 | void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req); |
1606 | void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb); | 1598 | void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb); |
1607 | int (*secmark_relabel_packet) (u32 secid); | 1599 | int (*secmark_relabel_packet) (u32 secid); |
1608 | void (*secmark_refcount_inc) (void); | 1600 | void (*secmark_refcount_inc) (void); |
1609 | void (*secmark_refcount_dec) (void); | 1601 | void (*secmark_refcount_dec) (void); |
1610 | void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl); | 1602 | void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl); |
1611 | int (*tun_dev_create)(void); | 1603 | int (*tun_dev_create)(void); |
1612 | void (*tun_dev_post_create)(struct sock *sk); | 1604 | void (*tun_dev_post_create)(struct sock *sk); |
1613 | int (*tun_dev_attach)(struct sock *sk); | 1605 | int (*tun_dev_attach)(struct sock *sk); |
1614 | #endif /* CONFIG_SECURITY_NETWORK */ | 1606 | #endif /* CONFIG_SECURITY_NETWORK */ |
1615 | 1607 | ||
1616 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1608 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1617 | int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp, | 1609 | int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp, |
1618 | struct xfrm_user_sec_ctx *sec_ctx); | 1610 | struct xfrm_user_sec_ctx *sec_ctx); |
1619 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); | 1611 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); |
1620 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); | 1612 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); |
1621 | int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); | 1613 | int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); |
1622 | int (*xfrm_state_alloc_security) (struct xfrm_state *x, | 1614 | int (*xfrm_state_alloc_security) (struct xfrm_state *x, |
1623 | struct xfrm_user_sec_ctx *sec_ctx, | 1615 | struct xfrm_user_sec_ctx *sec_ctx, |
1624 | u32 secid); | 1616 | u32 secid); |
1625 | void (*xfrm_state_free_security) (struct xfrm_state *x); | 1617 | void (*xfrm_state_free_security) (struct xfrm_state *x); |
1626 | int (*xfrm_state_delete_security) (struct xfrm_state *x); | 1618 | int (*xfrm_state_delete_security) (struct xfrm_state *x); |
1627 | int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); | 1619 | int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); |
1628 | int (*xfrm_state_pol_flow_match) (struct xfrm_state *x, | 1620 | int (*xfrm_state_pol_flow_match) (struct xfrm_state *x, |
1629 | struct xfrm_policy *xp, | 1621 | struct xfrm_policy *xp, |
1630 | const struct flowi *fl); | 1622 | const struct flowi *fl); |
1631 | int (*xfrm_decode_session) (struct sk_buff *skb, u32 *secid, int ckall); | 1623 | int (*xfrm_decode_session) (struct sk_buff *skb, u32 *secid, int ckall); |
1632 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 1624 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
1633 | 1625 | ||
1634 | /* key management security hooks */ | 1626 | /* key management security hooks */ |
1635 | #ifdef CONFIG_KEYS | 1627 | #ifdef CONFIG_KEYS |
1636 | int (*key_alloc) (struct key *key, const struct cred *cred, unsigned long flags); | 1628 | int (*key_alloc) (struct key *key, const struct cred *cred, unsigned long flags); |
1637 | void (*key_free) (struct key *key); | 1629 | void (*key_free) (struct key *key); |
1638 | int (*key_permission) (key_ref_t key_ref, | 1630 | int (*key_permission) (key_ref_t key_ref, |
1639 | const struct cred *cred, | 1631 | const struct cred *cred, |
1640 | key_perm_t perm); | 1632 | key_perm_t perm); |
1641 | int (*key_getsecurity)(struct key *key, char **_buffer); | 1633 | int (*key_getsecurity)(struct key *key, char **_buffer); |
1642 | #endif /* CONFIG_KEYS */ | 1634 | #endif /* CONFIG_KEYS */ |
1643 | 1635 | ||
1644 | #ifdef CONFIG_AUDIT | 1636 | #ifdef CONFIG_AUDIT |
1645 | int (*audit_rule_init) (u32 field, u32 op, char *rulestr, void **lsmrule); | 1637 | int (*audit_rule_init) (u32 field, u32 op, char *rulestr, void **lsmrule); |
1646 | int (*audit_rule_known) (struct audit_krule *krule); | 1638 | int (*audit_rule_known) (struct audit_krule *krule); |
1647 | int (*audit_rule_match) (u32 secid, u32 field, u32 op, void *lsmrule, | 1639 | int (*audit_rule_match) (u32 secid, u32 field, u32 op, void *lsmrule, |
1648 | struct audit_context *actx); | 1640 | struct audit_context *actx); |
1649 | void (*audit_rule_free) (void *lsmrule); | 1641 | void (*audit_rule_free) (void *lsmrule); |
1650 | #endif /* CONFIG_AUDIT */ | 1642 | #endif /* CONFIG_AUDIT */ |
1651 | }; | 1643 | }; |
1652 | 1644 | ||
1653 | /* prototypes */ | 1645 | /* prototypes */ |
1654 | extern int security_init(void); | 1646 | extern int security_init(void); |
1655 | extern int security_module_enable(struct security_operations *ops); | 1647 | extern int security_module_enable(struct security_operations *ops); |
1656 | extern int register_security(struct security_operations *ops); | 1648 | extern int register_security(struct security_operations *ops); |
1657 | 1649 | ||
1658 | /* Security operations */ | 1650 | /* Security operations */ |
1659 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode); | 1651 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode); |
1660 | int security_ptrace_traceme(struct task_struct *parent); | 1652 | int security_ptrace_traceme(struct task_struct *parent); |
1661 | int security_capget(struct task_struct *target, | 1653 | int security_capget(struct task_struct *target, |
1662 | kernel_cap_t *effective, | 1654 | kernel_cap_t *effective, |
1663 | kernel_cap_t *inheritable, | 1655 | kernel_cap_t *inheritable, |
1664 | kernel_cap_t *permitted); | 1656 | kernel_cap_t *permitted); |
1665 | int security_capset(struct cred *new, const struct cred *old, | 1657 | int security_capset(struct cred *new, const struct cred *old, |
1666 | const kernel_cap_t *effective, | 1658 | const kernel_cap_t *effective, |
1667 | const kernel_cap_t *inheritable, | 1659 | const kernel_cap_t *inheritable, |
1668 | const kernel_cap_t *permitted); | 1660 | const kernel_cap_t *permitted); |
1669 | int security_capable(const struct cred *cred, struct user_namespace *ns, | 1661 | int security_capable(const struct cred *cred, struct user_namespace *ns, |
1670 | int cap); | 1662 | int cap); |
1671 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, | 1663 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, |
1672 | int cap); | 1664 | int cap); |
1673 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); | 1665 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); |
1674 | int security_quota_on(struct dentry *dentry); | 1666 | int security_quota_on(struct dentry *dentry); |
1675 | int security_syslog(int type); | 1667 | int security_syslog(int type); |
1676 | int security_settime(const struct timespec *ts, const struct timezone *tz); | 1668 | int security_settime(const struct timespec *ts, const struct timezone *tz); |
1677 | int security_vm_enough_memory(long pages); | 1669 | int security_vm_enough_memory(long pages); |
1678 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); | 1670 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); |
1679 | int security_vm_enough_memory_kern(long pages); | 1671 | int security_vm_enough_memory_kern(long pages); |
1680 | int security_bprm_set_creds(struct linux_binprm *bprm); | 1672 | int security_bprm_set_creds(struct linux_binprm *bprm); |
1681 | int security_bprm_check(struct linux_binprm *bprm); | 1673 | int security_bprm_check(struct linux_binprm *bprm); |
1682 | void security_bprm_committing_creds(struct linux_binprm *bprm); | 1674 | void security_bprm_committing_creds(struct linux_binprm *bprm); |
1683 | void security_bprm_committed_creds(struct linux_binprm *bprm); | 1675 | void security_bprm_committed_creds(struct linux_binprm *bprm); |
1684 | int security_bprm_secureexec(struct linux_binprm *bprm); | 1676 | int security_bprm_secureexec(struct linux_binprm *bprm); |
1685 | int security_sb_alloc(struct super_block *sb); | 1677 | int security_sb_alloc(struct super_block *sb); |
1686 | void security_sb_free(struct super_block *sb); | 1678 | void security_sb_free(struct super_block *sb); |
1687 | int security_sb_copy_data(char *orig, char *copy); | 1679 | int security_sb_copy_data(char *orig, char *copy); |
1688 | int security_sb_remount(struct super_block *sb, void *data); | 1680 | int security_sb_remount(struct super_block *sb, void *data); |
1689 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data); | 1681 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data); |
1690 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); | 1682 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); |
1691 | int security_sb_statfs(struct dentry *dentry); | 1683 | int security_sb_statfs(struct dentry *dentry); |
1692 | int security_sb_mount(char *dev_name, struct path *path, | 1684 | int security_sb_mount(char *dev_name, struct path *path, |
1693 | char *type, unsigned long flags, void *data); | 1685 | char *type, unsigned long flags, void *data); |
1694 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1686 | int security_sb_umount(struct vfsmount *mnt, int flags); |
1695 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1687 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
1696 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 1688 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); |
1697 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1689 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, |
1698 | struct super_block *newsb); | 1690 | struct super_block *newsb); |
1699 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 1691 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
1700 | 1692 | ||
1701 | int security_inode_alloc(struct inode *inode); | 1693 | int security_inode_alloc(struct inode *inode); |
1702 | void security_inode_free(struct inode *inode); | 1694 | void security_inode_free(struct inode *inode); |
1703 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 1695 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
1704 | const struct qstr *qstr, char **name, | 1696 | const struct qstr *qstr, char **name, |
1705 | void **value, size_t *len); | 1697 | void **value, size_t *len); |
1706 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); | 1698 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); |
1707 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, | 1699 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, |
1708 | struct dentry *new_dentry); | 1700 | struct dentry *new_dentry); |
1709 | int security_inode_unlink(struct inode *dir, struct dentry *dentry); | 1701 | int security_inode_unlink(struct inode *dir, struct dentry *dentry); |
1710 | int security_inode_symlink(struct inode *dir, struct dentry *dentry, | 1702 | int security_inode_symlink(struct inode *dir, struct dentry *dentry, |
1711 | const char *old_name); | 1703 | const char *old_name); |
1712 | int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode); | 1704 | int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode); |
1713 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry); | 1705 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry); |
1714 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); | 1706 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); |
1715 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | 1707 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, |
1716 | struct inode *new_dir, struct dentry *new_dentry); | 1708 | struct inode *new_dir, struct dentry *new_dentry); |
1717 | int security_inode_readlink(struct dentry *dentry); | 1709 | int security_inode_readlink(struct dentry *dentry); |
1718 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); | 1710 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); |
1719 | int security_inode_permission(struct inode *inode, int mask); | 1711 | int security_inode_permission(struct inode *inode, int mask); |
1720 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); | 1712 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); |
1721 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); | 1713 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); |
1722 | int security_inode_setxattr(struct dentry *dentry, const char *name, | 1714 | int security_inode_setxattr(struct dentry *dentry, const char *name, |
1723 | const void *value, size_t size, int flags); | 1715 | const void *value, size_t size, int flags); |
1724 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, | 1716 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, |
1725 | const void *value, size_t size, int flags); | 1717 | const void *value, size_t size, int flags); |
1726 | int security_inode_getxattr(struct dentry *dentry, const char *name); | 1718 | int security_inode_getxattr(struct dentry *dentry, const char *name); |
1727 | int security_inode_listxattr(struct dentry *dentry); | 1719 | int security_inode_listxattr(struct dentry *dentry); |
1728 | int security_inode_removexattr(struct dentry *dentry, const char *name); | 1720 | int security_inode_removexattr(struct dentry *dentry, const char *name); |
1729 | int security_inode_need_killpriv(struct dentry *dentry); | 1721 | int security_inode_need_killpriv(struct dentry *dentry); |
1730 | int security_inode_killpriv(struct dentry *dentry); | 1722 | int security_inode_killpriv(struct dentry *dentry); |
1731 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc); | 1723 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc); |
1732 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); | 1724 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); |
1733 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); | 1725 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); |
1734 | void security_inode_getsecid(const struct inode *inode, u32 *secid); | 1726 | void security_inode_getsecid(const struct inode *inode, u32 *secid); |
1735 | int security_file_permission(struct file *file, int mask); | 1727 | int security_file_permission(struct file *file, int mask); |
1736 | int security_file_alloc(struct file *file); | 1728 | int security_file_alloc(struct file *file); |
1737 | void security_file_free(struct file *file); | 1729 | void security_file_free(struct file *file); |
1738 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 1730 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
1739 | int security_file_mmap(struct file *file, unsigned long reqprot, | 1731 | int security_file_mmap(struct file *file, unsigned long reqprot, |
1740 | unsigned long prot, unsigned long flags, | 1732 | unsigned long prot, unsigned long flags, |
1741 | unsigned long addr, unsigned long addr_only); | 1733 | unsigned long addr, unsigned long addr_only); |
1742 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 1734 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
1743 | unsigned long prot); | 1735 | unsigned long prot); |
1744 | int security_file_lock(struct file *file, unsigned int cmd); | 1736 | int security_file_lock(struct file *file, unsigned int cmd); |
1745 | int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg); | 1737 | int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg); |
1746 | int security_file_set_fowner(struct file *file); | 1738 | int security_file_set_fowner(struct file *file); |
1747 | int security_file_send_sigiotask(struct task_struct *tsk, | 1739 | int security_file_send_sigiotask(struct task_struct *tsk, |
1748 | struct fown_struct *fown, int sig); | 1740 | struct fown_struct *fown, int sig); |
1749 | int security_file_receive(struct file *file); | 1741 | int security_file_receive(struct file *file); |
1750 | int security_dentry_open(struct file *file, const struct cred *cred); | 1742 | int security_dentry_open(struct file *file, const struct cred *cred); |
1751 | int security_task_create(unsigned long clone_flags); | 1743 | int security_task_create(unsigned long clone_flags); |
1752 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); | 1744 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); |
1753 | void security_cred_free(struct cred *cred); | 1745 | void security_cred_free(struct cred *cred); |
1754 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); | 1746 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); |
1755 | void security_transfer_creds(struct cred *new, const struct cred *old); | 1747 | void security_transfer_creds(struct cred *new, const struct cred *old); |
1756 | int security_kernel_act_as(struct cred *new, u32 secid); | 1748 | int security_kernel_act_as(struct cred *new, u32 secid); |
1757 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); | 1749 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); |
1758 | int security_kernel_module_request(char *kmod_name); | 1750 | int security_kernel_module_request(char *kmod_name); |
1759 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 1751 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
1760 | int flags); | 1752 | int flags); |
1761 | int security_task_setpgid(struct task_struct *p, pid_t pgid); | 1753 | int security_task_setpgid(struct task_struct *p, pid_t pgid); |
1762 | int security_task_getpgid(struct task_struct *p); | 1754 | int security_task_getpgid(struct task_struct *p); |
1763 | int security_task_getsid(struct task_struct *p); | 1755 | int security_task_getsid(struct task_struct *p); |
1764 | void security_task_getsecid(struct task_struct *p, u32 *secid); | 1756 | void security_task_getsecid(struct task_struct *p, u32 *secid); |
1765 | int security_task_setnice(struct task_struct *p, int nice); | 1757 | int security_task_setnice(struct task_struct *p, int nice); |
1766 | int security_task_setioprio(struct task_struct *p, int ioprio); | 1758 | int security_task_setioprio(struct task_struct *p, int ioprio); |
1767 | int security_task_getioprio(struct task_struct *p); | 1759 | int security_task_getioprio(struct task_struct *p); |
1768 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, | 1760 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, |
1769 | struct rlimit *new_rlim); | 1761 | struct rlimit *new_rlim); |
1770 | int security_task_setscheduler(struct task_struct *p); | 1762 | int security_task_setscheduler(struct task_struct *p); |
1771 | int security_task_getscheduler(struct task_struct *p); | 1763 | int security_task_getscheduler(struct task_struct *p); |
1772 | int security_task_movememory(struct task_struct *p); | 1764 | int security_task_movememory(struct task_struct *p); |
1773 | int security_task_kill(struct task_struct *p, struct siginfo *info, | 1765 | int security_task_kill(struct task_struct *p, struct siginfo *info, |
1774 | int sig, u32 secid); | 1766 | int sig, u32 secid); |
1775 | int security_task_wait(struct task_struct *p); | 1767 | int security_task_wait(struct task_struct *p); |
1776 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 1768 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
1777 | unsigned long arg4, unsigned long arg5); | 1769 | unsigned long arg4, unsigned long arg5); |
1778 | void security_task_to_inode(struct task_struct *p, struct inode *inode); | 1770 | void security_task_to_inode(struct task_struct *p, struct inode *inode); |
1779 | int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag); | 1771 | int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag); |
1780 | void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid); | 1772 | void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid); |
1781 | int security_msg_msg_alloc(struct msg_msg *msg); | 1773 | int security_msg_msg_alloc(struct msg_msg *msg); |
1782 | void security_msg_msg_free(struct msg_msg *msg); | 1774 | void security_msg_msg_free(struct msg_msg *msg); |
1783 | int security_msg_queue_alloc(struct msg_queue *msq); | 1775 | int security_msg_queue_alloc(struct msg_queue *msq); |
1784 | void security_msg_queue_free(struct msg_queue *msq); | 1776 | void security_msg_queue_free(struct msg_queue *msq); |
1785 | int security_msg_queue_associate(struct msg_queue *msq, int msqflg); | 1777 | int security_msg_queue_associate(struct msg_queue *msq, int msqflg); |
1786 | int security_msg_queue_msgctl(struct msg_queue *msq, int cmd); | 1778 | int security_msg_queue_msgctl(struct msg_queue *msq, int cmd); |
1787 | int security_msg_queue_msgsnd(struct msg_queue *msq, | 1779 | int security_msg_queue_msgsnd(struct msg_queue *msq, |
1788 | struct msg_msg *msg, int msqflg); | 1780 | struct msg_msg *msg, int msqflg); |
1789 | int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | 1781 | int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, |
1790 | struct task_struct *target, long type, int mode); | 1782 | struct task_struct *target, long type, int mode); |
1791 | int security_shm_alloc(struct shmid_kernel *shp); | 1783 | int security_shm_alloc(struct shmid_kernel *shp); |
1792 | void security_shm_free(struct shmid_kernel *shp); | 1784 | void security_shm_free(struct shmid_kernel *shp); |
1793 | int security_shm_associate(struct shmid_kernel *shp, int shmflg); | 1785 | int security_shm_associate(struct shmid_kernel *shp, int shmflg); |
1794 | int security_shm_shmctl(struct shmid_kernel *shp, int cmd); | 1786 | int security_shm_shmctl(struct shmid_kernel *shp, int cmd); |
1795 | int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg); | 1787 | int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg); |
1796 | int security_sem_alloc(struct sem_array *sma); | 1788 | int security_sem_alloc(struct sem_array *sma); |
1797 | void security_sem_free(struct sem_array *sma); | 1789 | void security_sem_free(struct sem_array *sma); |
1798 | int security_sem_associate(struct sem_array *sma, int semflg); | 1790 | int security_sem_associate(struct sem_array *sma, int semflg); |
1799 | int security_sem_semctl(struct sem_array *sma, int cmd); | 1791 | int security_sem_semctl(struct sem_array *sma, int cmd); |
1800 | int security_sem_semop(struct sem_array *sma, struct sembuf *sops, | 1792 | int security_sem_semop(struct sem_array *sma, struct sembuf *sops, |
1801 | unsigned nsops, int alter); | 1793 | unsigned nsops, int alter); |
1802 | void security_d_instantiate(struct dentry *dentry, struct inode *inode); | 1794 | void security_d_instantiate(struct dentry *dentry, struct inode *inode); |
1803 | int security_getprocattr(struct task_struct *p, char *name, char **value); | 1795 | int security_getprocattr(struct task_struct *p, char *name, char **value); |
1804 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); | 1796 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); |
1805 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); | 1797 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); |
1806 | int security_netlink_recv(struct sk_buff *skb, int cap); | ||
1807 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 1798 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
1808 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 1799 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
1809 | void security_release_secctx(char *secdata, u32 seclen); | 1800 | void security_release_secctx(char *secdata, u32 seclen); |
1810 | 1801 | ||
1811 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); | 1802 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); |
1812 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); | 1803 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); |
1813 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); | 1804 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); |
1814 | #else /* CONFIG_SECURITY */ | 1805 | #else /* CONFIG_SECURITY */ |
1815 | struct security_mnt_opts { | 1806 | struct security_mnt_opts { |
1816 | }; | 1807 | }; |
1817 | 1808 | ||
1818 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) | 1809 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) |
1819 | { | 1810 | { |
1820 | } | 1811 | } |
1821 | 1812 | ||
1822 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | 1813 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) |
1823 | { | 1814 | { |
1824 | } | 1815 | } |
1825 | 1816 | ||
1826 | /* | 1817 | /* |
1827 | * This is the default capabilities functionality. Most of these functions | 1818 | * This is the default capabilities functionality. Most of these functions |
1828 | * are just stubbed out, but a few must call the proper capable code. | 1819 | * are just stubbed out, but a few must call the proper capable code. |
1829 | */ | 1820 | */ |
1830 | 1821 | ||
1831 | static inline int security_init(void) | 1822 | static inline int security_init(void) |
1832 | { | 1823 | { |
1833 | return 0; | 1824 | return 0; |
1834 | } | 1825 | } |
1835 | 1826 | ||
1836 | static inline int security_ptrace_access_check(struct task_struct *child, | 1827 | static inline int security_ptrace_access_check(struct task_struct *child, |
1837 | unsigned int mode) | 1828 | unsigned int mode) |
1838 | { | 1829 | { |
1839 | return cap_ptrace_access_check(child, mode); | 1830 | return cap_ptrace_access_check(child, mode); |
1840 | } | 1831 | } |
1841 | 1832 | ||
1842 | static inline int security_ptrace_traceme(struct task_struct *parent) | 1833 | static inline int security_ptrace_traceme(struct task_struct *parent) |
1843 | { | 1834 | { |
1844 | return cap_ptrace_traceme(parent); | 1835 | return cap_ptrace_traceme(parent); |
1845 | } | 1836 | } |
1846 | 1837 | ||
1847 | static inline int security_capget(struct task_struct *target, | 1838 | static inline int security_capget(struct task_struct *target, |
1848 | kernel_cap_t *effective, | 1839 | kernel_cap_t *effective, |
1849 | kernel_cap_t *inheritable, | 1840 | kernel_cap_t *inheritable, |
1850 | kernel_cap_t *permitted) | 1841 | kernel_cap_t *permitted) |
1851 | { | 1842 | { |
1852 | return cap_capget(target, effective, inheritable, permitted); | 1843 | return cap_capget(target, effective, inheritable, permitted); |
1853 | } | 1844 | } |
1854 | 1845 | ||
1855 | static inline int security_capset(struct cred *new, | 1846 | static inline int security_capset(struct cred *new, |
1856 | const struct cred *old, | 1847 | const struct cred *old, |
1857 | const kernel_cap_t *effective, | 1848 | const kernel_cap_t *effective, |
1858 | const kernel_cap_t *inheritable, | 1849 | const kernel_cap_t *inheritable, |
1859 | const kernel_cap_t *permitted) | 1850 | const kernel_cap_t *permitted) |
1860 | { | 1851 | { |
1861 | return cap_capset(new, old, effective, inheritable, permitted); | 1852 | return cap_capset(new, old, effective, inheritable, permitted); |
1862 | } | 1853 | } |
1863 | 1854 | ||
1864 | static inline int security_capable(const struct cred *cred, | 1855 | static inline int security_capable(const struct cred *cred, |
1865 | struct user_namespace *ns, int cap) | 1856 | struct user_namespace *ns, int cap) |
1866 | { | 1857 | { |
1867 | return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT); | 1858 | return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT); |
1868 | } | 1859 | } |
1869 | 1860 | ||
1870 | static inline int security_capable_noaudit(const struct cred *cred, | 1861 | static inline int security_capable_noaudit(const struct cred *cred, |
1871 | struct user_namespace *ns, int cap) { | 1862 | struct user_namespace *ns, int cap) { |
1872 | return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); | 1863 | return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); |
1873 | } | 1864 | } |
1874 | 1865 | ||
1875 | static inline int security_quotactl(int cmds, int type, int id, | 1866 | static inline int security_quotactl(int cmds, int type, int id, |
1876 | struct super_block *sb) | 1867 | struct super_block *sb) |
1877 | { | 1868 | { |
1878 | return 0; | 1869 | return 0; |
1879 | } | 1870 | } |
1880 | 1871 | ||
1881 | static inline int security_quota_on(struct dentry *dentry) | 1872 | static inline int security_quota_on(struct dentry *dentry) |
1882 | { | 1873 | { |
1883 | return 0; | 1874 | return 0; |
1884 | } | 1875 | } |
1885 | 1876 | ||
1886 | static inline int security_syslog(int type) | 1877 | static inline int security_syslog(int type) |
1887 | { | 1878 | { |
1888 | return 0; | 1879 | return 0; |
1889 | } | 1880 | } |
1890 | 1881 | ||
1891 | static inline int security_settime(const struct timespec *ts, | 1882 | static inline int security_settime(const struct timespec *ts, |
1892 | const struct timezone *tz) | 1883 | const struct timezone *tz) |
1893 | { | 1884 | { |
1894 | return cap_settime(ts, tz); | 1885 | return cap_settime(ts, tz); |
1895 | } | 1886 | } |
1896 | 1887 | ||
1897 | static inline int security_vm_enough_memory(long pages) | 1888 | static inline int security_vm_enough_memory(long pages) |
1898 | { | 1889 | { |
1899 | WARN_ON(current->mm == NULL); | 1890 | WARN_ON(current->mm == NULL); |
1900 | return cap_vm_enough_memory(current->mm, pages); | 1891 | return cap_vm_enough_memory(current->mm, pages); |
1901 | } | 1892 | } |
1902 | 1893 | ||
1903 | static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | 1894 | static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) |
1904 | { | 1895 | { |
1905 | WARN_ON(mm == NULL); | 1896 | WARN_ON(mm == NULL); |
1906 | return cap_vm_enough_memory(mm, pages); | 1897 | return cap_vm_enough_memory(mm, pages); |
1907 | } | 1898 | } |
1908 | 1899 | ||
1909 | static inline int security_vm_enough_memory_kern(long pages) | 1900 | static inline int security_vm_enough_memory_kern(long pages) |
1910 | { | 1901 | { |
1911 | /* If current->mm is a kernel thread then we will pass NULL, | 1902 | /* If current->mm is a kernel thread then we will pass NULL, |
1912 | for this specific case that is fine */ | 1903 | for this specific case that is fine */ |
1913 | return cap_vm_enough_memory(current->mm, pages); | 1904 | return cap_vm_enough_memory(current->mm, pages); |
1914 | } | 1905 | } |
1915 | 1906 | ||
1916 | static inline int security_bprm_set_creds(struct linux_binprm *bprm) | 1907 | static inline int security_bprm_set_creds(struct linux_binprm *bprm) |
1917 | { | 1908 | { |
1918 | return cap_bprm_set_creds(bprm); | 1909 | return cap_bprm_set_creds(bprm); |
1919 | } | 1910 | } |
1920 | 1911 | ||
1921 | static inline int security_bprm_check(struct linux_binprm *bprm) | 1912 | static inline int security_bprm_check(struct linux_binprm *bprm) |
1922 | { | 1913 | { |
1923 | return 0; | 1914 | return 0; |
1924 | } | 1915 | } |
1925 | 1916 | ||
1926 | static inline void security_bprm_committing_creds(struct linux_binprm *bprm) | 1917 | static inline void security_bprm_committing_creds(struct linux_binprm *bprm) |
1927 | { | 1918 | { |
1928 | } | 1919 | } |
1929 | 1920 | ||
1930 | static inline void security_bprm_committed_creds(struct linux_binprm *bprm) | 1921 | static inline void security_bprm_committed_creds(struct linux_binprm *bprm) |
1931 | { | 1922 | { |
1932 | } | 1923 | } |
1933 | 1924 | ||
1934 | static inline int security_bprm_secureexec(struct linux_binprm *bprm) | 1925 | static inline int security_bprm_secureexec(struct linux_binprm *bprm) |
1935 | { | 1926 | { |
1936 | return cap_bprm_secureexec(bprm); | 1927 | return cap_bprm_secureexec(bprm); |
1937 | } | 1928 | } |
1938 | 1929 | ||
1939 | static inline int security_sb_alloc(struct super_block *sb) | 1930 | static inline int security_sb_alloc(struct super_block *sb) |
1940 | { | 1931 | { |
1941 | return 0; | 1932 | return 0; |
1942 | } | 1933 | } |
1943 | 1934 | ||
1944 | static inline void security_sb_free(struct super_block *sb) | 1935 | static inline void security_sb_free(struct super_block *sb) |
1945 | { } | 1936 | { } |
1946 | 1937 | ||
1947 | static inline int security_sb_copy_data(char *orig, char *copy) | 1938 | static inline int security_sb_copy_data(char *orig, char *copy) |
1948 | { | 1939 | { |
1949 | return 0; | 1940 | return 0; |
1950 | } | 1941 | } |
1951 | 1942 | ||
1952 | static inline int security_sb_remount(struct super_block *sb, void *data) | 1943 | static inline int security_sb_remount(struct super_block *sb, void *data) |
1953 | { | 1944 | { |
1954 | return 0; | 1945 | return 0; |
1955 | } | 1946 | } |
1956 | 1947 | ||
1957 | static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) | 1948 | static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
1958 | { | 1949 | { |
1959 | return 0; | 1950 | return 0; |
1960 | } | 1951 | } |
1961 | 1952 | ||
1962 | static inline int security_sb_show_options(struct seq_file *m, | 1953 | static inline int security_sb_show_options(struct seq_file *m, |
1963 | struct super_block *sb) | 1954 | struct super_block *sb) |
1964 | { | 1955 | { |
1965 | return 0; | 1956 | return 0; |
1966 | } | 1957 | } |
1967 | 1958 | ||
1968 | static inline int security_sb_statfs(struct dentry *dentry) | 1959 | static inline int security_sb_statfs(struct dentry *dentry) |
1969 | { | 1960 | { |
1970 | return 0; | 1961 | return 0; |
1971 | } | 1962 | } |
1972 | 1963 | ||
1973 | static inline int security_sb_mount(char *dev_name, struct path *path, | 1964 | static inline int security_sb_mount(char *dev_name, struct path *path, |
1974 | char *type, unsigned long flags, | 1965 | char *type, unsigned long flags, |
1975 | void *data) | 1966 | void *data) |
1976 | { | 1967 | { |
1977 | return 0; | 1968 | return 0; |
1978 | } | 1969 | } |
1979 | 1970 | ||
1980 | static inline int security_sb_umount(struct vfsmount *mnt, int flags) | 1971 | static inline int security_sb_umount(struct vfsmount *mnt, int flags) |
1981 | { | 1972 | { |
1982 | return 0; | 1973 | return 0; |
1983 | } | 1974 | } |
1984 | 1975 | ||
1985 | static inline int security_sb_pivotroot(struct path *old_path, | 1976 | static inline int security_sb_pivotroot(struct path *old_path, |
1986 | struct path *new_path) | 1977 | struct path *new_path) |
1987 | { | 1978 | { |
1988 | return 0; | 1979 | return 0; |
1989 | } | 1980 | } |
1990 | 1981 | ||
1991 | static inline int security_sb_set_mnt_opts(struct super_block *sb, | 1982 | static inline int security_sb_set_mnt_opts(struct super_block *sb, |
1992 | struct security_mnt_opts *opts) | 1983 | struct security_mnt_opts *opts) |
1993 | { | 1984 | { |
1994 | return 0; | 1985 | return 0; |
1995 | } | 1986 | } |
1996 | 1987 | ||
1997 | static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1988 | static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, |
1998 | struct super_block *newsb) | 1989 | struct super_block *newsb) |
1999 | { } | 1990 | { } |
2000 | 1991 | ||
2001 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 1992 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
2002 | { | 1993 | { |
2003 | return 0; | 1994 | return 0; |
2004 | } | 1995 | } |
2005 | 1996 | ||
2006 | static inline int security_inode_alloc(struct inode *inode) | 1997 | static inline int security_inode_alloc(struct inode *inode) |
2007 | { | 1998 | { |
2008 | return 0; | 1999 | return 0; |
2009 | } | 2000 | } |
2010 | 2001 | ||
2011 | static inline void security_inode_free(struct inode *inode) | 2002 | static inline void security_inode_free(struct inode *inode) |
2012 | { } | 2003 | { } |
2013 | 2004 | ||
2014 | static inline int security_inode_init_security(struct inode *inode, | 2005 | static inline int security_inode_init_security(struct inode *inode, |
2015 | struct inode *dir, | 2006 | struct inode *dir, |
2016 | const struct qstr *qstr, | 2007 | const struct qstr *qstr, |
2017 | char **name, | 2008 | char **name, |
2018 | void **value, | 2009 | void **value, |
2019 | size_t *len) | 2010 | size_t *len) |
2020 | { | 2011 | { |
2021 | return -EOPNOTSUPP; | 2012 | return -EOPNOTSUPP; |
2022 | } | 2013 | } |
2023 | 2014 | ||
2024 | static inline int security_inode_create(struct inode *dir, | 2015 | static inline int security_inode_create(struct inode *dir, |
2025 | struct dentry *dentry, | 2016 | struct dentry *dentry, |
2026 | int mode) | 2017 | int mode) |
2027 | { | 2018 | { |
2028 | return 0; | 2019 | return 0; |
2029 | } | 2020 | } |
2030 | 2021 | ||
2031 | static inline int security_inode_link(struct dentry *old_dentry, | 2022 | static inline int security_inode_link(struct dentry *old_dentry, |
2032 | struct inode *dir, | 2023 | struct inode *dir, |
2033 | struct dentry *new_dentry) | 2024 | struct dentry *new_dentry) |
2034 | { | 2025 | { |
2035 | return 0; | 2026 | return 0; |
2036 | } | 2027 | } |
2037 | 2028 | ||
2038 | static inline int security_inode_unlink(struct inode *dir, | 2029 | static inline int security_inode_unlink(struct inode *dir, |
2039 | struct dentry *dentry) | 2030 | struct dentry *dentry) |
2040 | { | 2031 | { |
2041 | return 0; | 2032 | return 0; |
2042 | } | 2033 | } |
2043 | 2034 | ||
2044 | static inline int security_inode_symlink(struct inode *dir, | 2035 | static inline int security_inode_symlink(struct inode *dir, |
2045 | struct dentry *dentry, | 2036 | struct dentry *dentry, |
2046 | const char *old_name) | 2037 | const char *old_name) |
2047 | { | 2038 | { |
2048 | return 0; | 2039 | return 0; |
2049 | } | 2040 | } |
2050 | 2041 | ||
2051 | static inline int security_inode_mkdir(struct inode *dir, | 2042 | static inline int security_inode_mkdir(struct inode *dir, |
2052 | struct dentry *dentry, | 2043 | struct dentry *dentry, |
2053 | int mode) | 2044 | int mode) |
2054 | { | 2045 | { |
2055 | return 0; | 2046 | return 0; |
2056 | } | 2047 | } |
2057 | 2048 | ||
2058 | static inline int security_inode_rmdir(struct inode *dir, | 2049 | static inline int security_inode_rmdir(struct inode *dir, |
2059 | struct dentry *dentry) | 2050 | struct dentry *dentry) |
2060 | { | 2051 | { |
2061 | return 0; | 2052 | return 0; |
2062 | } | 2053 | } |
2063 | 2054 | ||
2064 | static inline int security_inode_mknod(struct inode *dir, | 2055 | static inline int security_inode_mknod(struct inode *dir, |
2065 | struct dentry *dentry, | 2056 | struct dentry *dentry, |
2066 | int mode, dev_t dev) | 2057 | int mode, dev_t dev) |
2067 | { | 2058 | { |
2068 | return 0; | 2059 | return 0; |
2069 | } | 2060 | } |
2070 | 2061 | ||
2071 | static inline int security_inode_rename(struct inode *old_dir, | 2062 | static inline int security_inode_rename(struct inode *old_dir, |
2072 | struct dentry *old_dentry, | 2063 | struct dentry *old_dentry, |
2073 | struct inode *new_dir, | 2064 | struct inode *new_dir, |
2074 | struct dentry *new_dentry) | 2065 | struct dentry *new_dentry) |
2075 | { | 2066 | { |
2076 | return 0; | 2067 | return 0; |
2077 | } | 2068 | } |
2078 | 2069 | ||
2079 | static inline int security_inode_readlink(struct dentry *dentry) | 2070 | static inline int security_inode_readlink(struct dentry *dentry) |
2080 | { | 2071 | { |
2081 | return 0; | 2072 | return 0; |
2082 | } | 2073 | } |
2083 | 2074 | ||
2084 | static inline int security_inode_follow_link(struct dentry *dentry, | 2075 | static inline int security_inode_follow_link(struct dentry *dentry, |
2085 | struct nameidata *nd) | 2076 | struct nameidata *nd) |
2086 | { | 2077 | { |
2087 | return 0; | 2078 | return 0; |
2088 | } | 2079 | } |
2089 | 2080 | ||
2090 | static inline int security_inode_permission(struct inode *inode, int mask) | 2081 | static inline int security_inode_permission(struct inode *inode, int mask) |
2091 | { | 2082 | { |
2092 | return 0; | 2083 | return 0; |
2093 | } | 2084 | } |
2094 | 2085 | ||
2095 | static inline int security_inode_setattr(struct dentry *dentry, | 2086 | static inline int security_inode_setattr(struct dentry *dentry, |
2096 | struct iattr *attr) | 2087 | struct iattr *attr) |
2097 | { | 2088 | { |
2098 | return 0; | 2089 | return 0; |
2099 | } | 2090 | } |
2100 | 2091 | ||
2101 | static inline int security_inode_getattr(struct vfsmount *mnt, | 2092 | static inline int security_inode_getattr(struct vfsmount *mnt, |
2102 | struct dentry *dentry) | 2093 | struct dentry *dentry) |
2103 | { | 2094 | { |
2104 | return 0; | 2095 | return 0; |
2105 | } | 2096 | } |
2106 | 2097 | ||
2107 | static inline int security_inode_setxattr(struct dentry *dentry, | 2098 | static inline int security_inode_setxattr(struct dentry *dentry, |
2108 | const char *name, const void *value, size_t size, int flags) | 2099 | const char *name, const void *value, size_t size, int flags) |
2109 | { | 2100 | { |
2110 | return cap_inode_setxattr(dentry, name, value, size, flags); | 2101 | return cap_inode_setxattr(dentry, name, value, size, flags); |
2111 | } | 2102 | } |
2112 | 2103 | ||
2113 | static inline void security_inode_post_setxattr(struct dentry *dentry, | 2104 | static inline void security_inode_post_setxattr(struct dentry *dentry, |
2114 | const char *name, const void *value, size_t size, int flags) | 2105 | const char *name, const void *value, size_t size, int flags) |
2115 | { } | 2106 | { } |
2116 | 2107 | ||
2117 | static inline int security_inode_getxattr(struct dentry *dentry, | 2108 | static inline int security_inode_getxattr(struct dentry *dentry, |
2118 | const char *name) | 2109 | const char *name) |
2119 | { | 2110 | { |
2120 | return 0; | 2111 | return 0; |
2121 | } | 2112 | } |
2122 | 2113 | ||
2123 | static inline int security_inode_listxattr(struct dentry *dentry) | 2114 | static inline int security_inode_listxattr(struct dentry *dentry) |
2124 | { | 2115 | { |
2125 | return 0; | 2116 | return 0; |
2126 | } | 2117 | } |
2127 | 2118 | ||
2128 | static inline int security_inode_removexattr(struct dentry *dentry, | 2119 | static inline int security_inode_removexattr(struct dentry *dentry, |
2129 | const char *name) | 2120 | const char *name) |
2130 | { | 2121 | { |
2131 | return cap_inode_removexattr(dentry, name); | 2122 | return cap_inode_removexattr(dentry, name); |
2132 | } | 2123 | } |
2133 | 2124 | ||
2134 | static inline int security_inode_need_killpriv(struct dentry *dentry) | 2125 | static inline int security_inode_need_killpriv(struct dentry *dentry) |
2135 | { | 2126 | { |
2136 | return cap_inode_need_killpriv(dentry); | 2127 | return cap_inode_need_killpriv(dentry); |
2137 | } | 2128 | } |
2138 | 2129 | ||
2139 | static inline int security_inode_killpriv(struct dentry *dentry) | 2130 | static inline int security_inode_killpriv(struct dentry *dentry) |
2140 | { | 2131 | { |
2141 | return cap_inode_killpriv(dentry); | 2132 | return cap_inode_killpriv(dentry); |
2142 | } | 2133 | } |
2143 | 2134 | ||
2144 | static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) | 2135 | static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
2145 | { | 2136 | { |
2146 | return -EOPNOTSUPP; | 2137 | return -EOPNOTSUPP; |
2147 | } | 2138 | } |
2148 | 2139 | ||
2149 | static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) | 2140 | static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) |
2150 | { | 2141 | { |
2151 | return -EOPNOTSUPP; | 2142 | return -EOPNOTSUPP; |
2152 | } | 2143 | } |
2153 | 2144 | ||
2154 | static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) | 2145 | static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) |
2155 | { | 2146 | { |
2156 | return 0; | 2147 | return 0; |
2157 | } | 2148 | } |
2158 | 2149 | ||
2159 | static inline void security_inode_getsecid(const struct inode *inode, u32 *secid) | 2150 | static inline void security_inode_getsecid(const struct inode *inode, u32 *secid) |
2160 | { | 2151 | { |
2161 | *secid = 0; | 2152 | *secid = 0; |
2162 | } | 2153 | } |
2163 | 2154 | ||
2164 | static inline int security_file_permission(struct file *file, int mask) | 2155 | static inline int security_file_permission(struct file *file, int mask) |
2165 | { | 2156 | { |
2166 | return 0; | 2157 | return 0; |
2167 | } | 2158 | } |
2168 | 2159 | ||
2169 | static inline int security_file_alloc(struct file *file) | 2160 | static inline int security_file_alloc(struct file *file) |
2170 | { | 2161 | { |
2171 | return 0; | 2162 | return 0; |
2172 | } | 2163 | } |
2173 | 2164 | ||
2174 | static inline void security_file_free(struct file *file) | 2165 | static inline void security_file_free(struct file *file) |
2175 | { } | 2166 | { } |
2176 | 2167 | ||
2177 | static inline int security_file_ioctl(struct file *file, unsigned int cmd, | 2168 | static inline int security_file_ioctl(struct file *file, unsigned int cmd, |
2178 | unsigned long arg) | 2169 | unsigned long arg) |
2179 | { | 2170 | { |
2180 | return 0; | 2171 | return 0; |
2181 | } | 2172 | } |
2182 | 2173 | ||
2183 | static inline int security_file_mmap(struct file *file, unsigned long reqprot, | 2174 | static inline int security_file_mmap(struct file *file, unsigned long reqprot, |
2184 | unsigned long prot, | 2175 | unsigned long prot, |
2185 | unsigned long flags, | 2176 | unsigned long flags, |
2186 | unsigned long addr, | 2177 | unsigned long addr, |
2187 | unsigned long addr_only) | 2178 | unsigned long addr_only) |
2188 | { | 2179 | { |
2189 | return cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 2180 | return cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); |
2190 | } | 2181 | } |
2191 | 2182 | ||
2192 | static inline int security_file_mprotect(struct vm_area_struct *vma, | 2183 | static inline int security_file_mprotect(struct vm_area_struct *vma, |
2193 | unsigned long reqprot, | 2184 | unsigned long reqprot, |
2194 | unsigned long prot) | 2185 | unsigned long prot) |
2195 | { | 2186 | { |
2196 | return 0; | 2187 | return 0; |
2197 | } | 2188 | } |
2198 | 2189 | ||
2199 | static inline int security_file_lock(struct file *file, unsigned int cmd) | 2190 | static inline int security_file_lock(struct file *file, unsigned int cmd) |
2200 | { | 2191 | { |
2201 | return 0; | 2192 | return 0; |
2202 | } | 2193 | } |
2203 | 2194 | ||
2204 | static inline int security_file_fcntl(struct file *file, unsigned int cmd, | 2195 | static inline int security_file_fcntl(struct file *file, unsigned int cmd, |
2205 | unsigned long arg) | 2196 | unsigned long arg) |
2206 | { | 2197 | { |
2207 | return 0; | 2198 | return 0; |
2208 | } | 2199 | } |
2209 | 2200 | ||
2210 | static inline int security_file_set_fowner(struct file *file) | 2201 | static inline int security_file_set_fowner(struct file *file) |
2211 | { | 2202 | { |
2212 | return 0; | 2203 | return 0; |
2213 | } | 2204 | } |
2214 | 2205 | ||
2215 | static inline int security_file_send_sigiotask(struct task_struct *tsk, | 2206 | static inline int security_file_send_sigiotask(struct task_struct *tsk, |
2216 | struct fown_struct *fown, | 2207 | struct fown_struct *fown, |
2217 | int sig) | 2208 | int sig) |
2218 | { | 2209 | { |
2219 | return 0; | 2210 | return 0; |
2220 | } | 2211 | } |
2221 | 2212 | ||
2222 | static inline int security_file_receive(struct file *file) | 2213 | static inline int security_file_receive(struct file *file) |
2223 | { | 2214 | { |
2224 | return 0; | 2215 | return 0; |
2225 | } | 2216 | } |
2226 | 2217 | ||
2227 | static inline int security_dentry_open(struct file *file, | 2218 | static inline int security_dentry_open(struct file *file, |
2228 | const struct cred *cred) | 2219 | const struct cred *cred) |
2229 | { | 2220 | { |
2230 | return 0; | 2221 | return 0; |
2231 | } | 2222 | } |
2232 | 2223 | ||
2233 | static inline int security_task_create(unsigned long clone_flags) | 2224 | static inline int security_task_create(unsigned long clone_flags) |
2234 | { | 2225 | { |
2235 | return 0; | 2226 | return 0; |
2236 | } | 2227 | } |
2237 | 2228 | ||
2238 | static inline int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 2229 | static inline int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
2239 | { | 2230 | { |
2240 | return 0; | 2231 | return 0; |
2241 | } | 2232 | } |
2242 | 2233 | ||
2243 | static inline void security_cred_free(struct cred *cred) | 2234 | static inline void security_cred_free(struct cred *cred) |
2244 | { } | 2235 | { } |
2245 | 2236 | ||
2246 | static inline int security_prepare_creds(struct cred *new, | 2237 | static inline int security_prepare_creds(struct cred *new, |
2247 | const struct cred *old, | 2238 | const struct cred *old, |
2248 | gfp_t gfp) | 2239 | gfp_t gfp) |
2249 | { | 2240 | { |
2250 | return 0; | 2241 | return 0; |
2251 | } | 2242 | } |
2252 | 2243 | ||
2253 | static inline void security_transfer_creds(struct cred *new, | 2244 | static inline void security_transfer_creds(struct cred *new, |
2254 | const struct cred *old) | 2245 | const struct cred *old) |
2255 | { | 2246 | { |
2256 | } | 2247 | } |
2257 | 2248 | ||
2258 | static inline int security_kernel_act_as(struct cred *cred, u32 secid) | 2249 | static inline int security_kernel_act_as(struct cred *cred, u32 secid) |
2259 | { | 2250 | { |
2260 | return 0; | 2251 | return 0; |
2261 | } | 2252 | } |
2262 | 2253 | ||
2263 | static inline int security_kernel_create_files_as(struct cred *cred, | 2254 | static inline int security_kernel_create_files_as(struct cred *cred, |
2264 | struct inode *inode) | 2255 | struct inode *inode) |
2265 | { | 2256 | { |
2266 | return 0; | 2257 | return 0; |
2267 | } | 2258 | } |
2268 | 2259 | ||
2269 | static inline int security_kernel_module_request(char *kmod_name) | 2260 | static inline int security_kernel_module_request(char *kmod_name) |
2270 | { | 2261 | { |
2271 | return 0; | 2262 | return 0; |
2272 | } | 2263 | } |
2273 | 2264 | ||
2274 | static inline int security_task_fix_setuid(struct cred *new, | 2265 | static inline int security_task_fix_setuid(struct cred *new, |
2275 | const struct cred *old, | 2266 | const struct cred *old, |
2276 | int flags) | 2267 | int flags) |
2277 | { | 2268 | { |
2278 | return cap_task_fix_setuid(new, old, flags); | 2269 | return cap_task_fix_setuid(new, old, flags); |
2279 | } | 2270 | } |
2280 | 2271 | ||
2281 | static inline int security_task_setpgid(struct task_struct *p, pid_t pgid) | 2272 | static inline int security_task_setpgid(struct task_struct *p, pid_t pgid) |
2282 | { | 2273 | { |
2283 | return 0; | 2274 | return 0; |
2284 | } | 2275 | } |
2285 | 2276 | ||
2286 | static inline int security_task_getpgid(struct task_struct *p) | 2277 | static inline int security_task_getpgid(struct task_struct *p) |
2287 | { | 2278 | { |
2288 | return 0; | 2279 | return 0; |
2289 | } | 2280 | } |
2290 | 2281 | ||
2291 | static inline int security_task_getsid(struct task_struct *p) | 2282 | static inline int security_task_getsid(struct task_struct *p) |
2292 | { | 2283 | { |
2293 | return 0; | 2284 | return 0; |
2294 | } | 2285 | } |
2295 | 2286 | ||
2296 | static inline void security_task_getsecid(struct task_struct *p, u32 *secid) | 2287 | static inline void security_task_getsecid(struct task_struct *p, u32 *secid) |
2297 | { | 2288 | { |
2298 | *secid = 0; | 2289 | *secid = 0; |
2299 | } | 2290 | } |
2300 | 2291 | ||
2301 | static inline int security_task_setnice(struct task_struct *p, int nice) | 2292 | static inline int security_task_setnice(struct task_struct *p, int nice) |
2302 | { | 2293 | { |
2303 | return cap_task_setnice(p, nice); | 2294 | return cap_task_setnice(p, nice); |
2304 | } | 2295 | } |
2305 | 2296 | ||
2306 | static inline int security_task_setioprio(struct task_struct *p, int ioprio) | 2297 | static inline int security_task_setioprio(struct task_struct *p, int ioprio) |
2307 | { | 2298 | { |
2308 | return cap_task_setioprio(p, ioprio); | 2299 | return cap_task_setioprio(p, ioprio); |
2309 | } | 2300 | } |
2310 | 2301 | ||
2311 | static inline int security_task_getioprio(struct task_struct *p) | 2302 | static inline int security_task_getioprio(struct task_struct *p) |
2312 | { | 2303 | { |
2313 | return 0; | 2304 | return 0; |
2314 | } | 2305 | } |
2315 | 2306 | ||
2316 | static inline int security_task_setrlimit(struct task_struct *p, | 2307 | static inline int security_task_setrlimit(struct task_struct *p, |
2317 | unsigned int resource, | 2308 | unsigned int resource, |
2318 | struct rlimit *new_rlim) | 2309 | struct rlimit *new_rlim) |
2319 | { | 2310 | { |
2320 | return 0; | 2311 | return 0; |
2321 | } | 2312 | } |
2322 | 2313 | ||
2323 | static inline int security_task_setscheduler(struct task_struct *p) | 2314 | static inline int security_task_setscheduler(struct task_struct *p) |
2324 | { | 2315 | { |
2325 | return cap_task_setscheduler(p); | 2316 | return cap_task_setscheduler(p); |
2326 | } | 2317 | } |
2327 | 2318 | ||
2328 | static inline int security_task_getscheduler(struct task_struct *p) | 2319 | static inline int security_task_getscheduler(struct task_struct *p) |
2329 | { | 2320 | { |
2330 | return 0; | 2321 | return 0; |
2331 | } | 2322 | } |
2332 | 2323 | ||
2333 | static inline int security_task_movememory(struct task_struct *p) | 2324 | static inline int security_task_movememory(struct task_struct *p) |
2334 | { | 2325 | { |
2335 | return 0; | 2326 | return 0; |
2336 | } | 2327 | } |
2337 | 2328 | ||
2338 | static inline int security_task_kill(struct task_struct *p, | 2329 | static inline int security_task_kill(struct task_struct *p, |
2339 | struct siginfo *info, int sig, | 2330 | struct siginfo *info, int sig, |
2340 | u32 secid) | 2331 | u32 secid) |
2341 | { | 2332 | { |
2342 | return 0; | 2333 | return 0; |
2343 | } | 2334 | } |
2344 | 2335 | ||
2345 | static inline int security_task_wait(struct task_struct *p) | 2336 | static inline int security_task_wait(struct task_struct *p) |
2346 | { | 2337 | { |
2347 | return 0; | 2338 | return 0; |
2348 | } | 2339 | } |
2349 | 2340 | ||
2350 | static inline int security_task_prctl(int option, unsigned long arg2, | 2341 | static inline int security_task_prctl(int option, unsigned long arg2, |
2351 | unsigned long arg3, | 2342 | unsigned long arg3, |
2352 | unsigned long arg4, | 2343 | unsigned long arg4, |
2353 | unsigned long arg5) | 2344 | unsigned long arg5) |
2354 | { | 2345 | { |
2355 | return cap_task_prctl(option, arg2, arg3, arg3, arg5); | 2346 | return cap_task_prctl(option, arg2, arg3, arg3, arg5); |
2356 | } | 2347 | } |
2357 | 2348 | ||
2358 | static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) | 2349 | static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) |
2359 | { } | 2350 | { } |
2360 | 2351 | ||
2361 | static inline int security_ipc_permission(struct kern_ipc_perm *ipcp, | 2352 | static inline int security_ipc_permission(struct kern_ipc_perm *ipcp, |
2362 | short flag) | 2353 | short flag) |
2363 | { | 2354 | { |
2364 | return 0; | 2355 | return 0; |
2365 | } | 2356 | } |
2366 | 2357 | ||
2367 | static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | 2358 | static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) |
2368 | { | 2359 | { |
2369 | *secid = 0; | 2360 | *secid = 0; |
2370 | } | 2361 | } |
2371 | 2362 | ||
2372 | static inline int security_msg_msg_alloc(struct msg_msg *msg) | 2363 | static inline int security_msg_msg_alloc(struct msg_msg *msg) |
2373 | { | 2364 | { |
2374 | return 0; | 2365 | return 0; |
2375 | } | 2366 | } |
2376 | 2367 | ||
2377 | static inline void security_msg_msg_free(struct msg_msg *msg) | 2368 | static inline void security_msg_msg_free(struct msg_msg *msg) |
2378 | { } | 2369 | { } |
2379 | 2370 | ||
2380 | static inline int security_msg_queue_alloc(struct msg_queue *msq) | 2371 | static inline int security_msg_queue_alloc(struct msg_queue *msq) |
2381 | { | 2372 | { |
2382 | return 0; | 2373 | return 0; |
2383 | } | 2374 | } |
2384 | 2375 | ||
2385 | static inline void security_msg_queue_free(struct msg_queue *msq) | 2376 | static inline void security_msg_queue_free(struct msg_queue *msq) |
2386 | { } | 2377 | { } |
2387 | 2378 | ||
2388 | static inline int security_msg_queue_associate(struct msg_queue *msq, | 2379 | static inline int security_msg_queue_associate(struct msg_queue *msq, |
2389 | int msqflg) | 2380 | int msqflg) |
2390 | { | 2381 | { |
2391 | return 0; | 2382 | return 0; |
2392 | } | 2383 | } |
2393 | 2384 | ||
2394 | static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) | 2385 | static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) |
2395 | { | 2386 | { |
2396 | return 0; | 2387 | return 0; |
2397 | } | 2388 | } |
2398 | 2389 | ||
2399 | static inline int security_msg_queue_msgsnd(struct msg_queue *msq, | 2390 | static inline int security_msg_queue_msgsnd(struct msg_queue *msq, |
2400 | struct msg_msg *msg, int msqflg) | 2391 | struct msg_msg *msg, int msqflg) |
2401 | { | 2392 | { |
2402 | return 0; | 2393 | return 0; |
2403 | } | 2394 | } |
2404 | 2395 | ||
2405 | static inline int security_msg_queue_msgrcv(struct msg_queue *msq, | 2396 | static inline int security_msg_queue_msgrcv(struct msg_queue *msq, |
2406 | struct msg_msg *msg, | 2397 | struct msg_msg *msg, |
2407 | struct task_struct *target, | 2398 | struct task_struct *target, |
2408 | long type, int mode) | 2399 | long type, int mode) |
2409 | { | 2400 | { |
2410 | return 0; | 2401 | return 0; |
2411 | } | 2402 | } |
2412 | 2403 | ||
2413 | static inline int security_shm_alloc(struct shmid_kernel *shp) | 2404 | static inline int security_shm_alloc(struct shmid_kernel *shp) |
2414 | { | 2405 | { |
2415 | return 0; | 2406 | return 0; |
2416 | } | 2407 | } |
2417 | 2408 | ||
2418 | static inline void security_shm_free(struct shmid_kernel *shp) | 2409 | static inline void security_shm_free(struct shmid_kernel *shp) |
2419 | { } | 2410 | { } |
2420 | 2411 | ||
2421 | static inline int security_shm_associate(struct shmid_kernel *shp, | 2412 | static inline int security_shm_associate(struct shmid_kernel *shp, |
2422 | int shmflg) | 2413 | int shmflg) |
2423 | { | 2414 | { |
2424 | return 0; | 2415 | return 0; |
2425 | } | 2416 | } |
2426 | 2417 | ||
2427 | static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd) | 2418 | static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd) |
2428 | { | 2419 | { |
2429 | return 0; | 2420 | return 0; |
2430 | } | 2421 | } |
2431 | 2422 | ||
2432 | static inline int security_shm_shmat(struct shmid_kernel *shp, | 2423 | static inline int security_shm_shmat(struct shmid_kernel *shp, |
2433 | char __user *shmaddr, int shmflg) | 2424 | char __user *shmaddr, int shmflg) |
2434 | { | 2425 | { |
2435 | return 0; | 2426 | return 0; |
2436 | } | 2427 | } |
2437 | 2428 | ||
2438 | static inline int security_sem_alloc(struct sem_array *sma) | 2429 | static inline int security_sem_alloc(struct sem_array *sma) |
2439 | { | 2430 | { |
2440 | return 0; | 2431 | return 0; |
2441 | } | 2432 | } |
2442 | 2433 | ||
2443 | static inline void security_sem_free(struct sem_array *sma) | 2434 | static inline void security_sem_free(struct sem_array *sma) |
2444 | { } | 2435 | { } |
2445 | 2436 | ||
2446 | static inline int security_sem_associate(struct sem_array *sma, int semflg) | 2437 | static inline int security_sem_associate(struct sem_array *sma, int semflg) |
2447 | { | 2438 | { |
2448 | return 0; | 2439 | return 0; |
2449 | } | 2440 | } |
2450 | 2441 | ||
2451 | static inline int security_sem_semctl(struct sem_array *sma, int cmd) | 2442 | static inline int security_sem_semctl(struct sem_array *sma, int cmd) |
2452 | { | 2443 | { |
2453 | return 0; | 2444 | return 0; |
2454 | } | 2445 | } |
2455 | 2446 | ||
2456 | static inline int security_sem_semop(struct sem_array *sma, | 2447 | static inline int security_sem_semop(struct sem_array *sma, |
2457 | struct sembuf *sops, unsigned nsops, | 2448 | struct sembuf *sops, unsigned nsops, |
2458 | int alter) | 2449 | int alter) |
2459 | { | 2450 | { |
2460 | return 0; | 2451 | return 0; |
2461 | } | 2452 | } |
2462 | 2453 | ||
2463 | static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode) | 2454 | static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode) |
2464 | { } | 2455 | { } |
2465 | 2456 | ||
2466 | static inline int security_getprocattr(struct task_struct *p, char *name, char **value) | 2457 | static inline int security_getprocattr(struct task_struct *p, char *name, char **value) |
2467 | { | 2458 | { |
2468 | return -EINVAL; | 2459 | return -EINVAL; |
2469 | } | 2460 | } |
2470 | 2461 | ||
2471 | static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) | 2462 | static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) |
2472 | { | 2463 | { |
2473 | return -EINVAL; | 2464 | return -EINVAL; |
2474 | } | 2465 | } |
2475 | 2466 | ||
2476 | static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 2467 | static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
2477 | { | 2468 | { |
2478 | return cap_netlink_send(sk, skb); | 2469 | return cap_netlink_send(sk, skb); |
2479 | } | ||
2480 | |||
2481 | static inline int security_netlink_recv(struct sk_buff *skb, int cap) | ||
2482 | { | ||
2483 | return cap_netlink_recv(skb, cap); | ||
2484 | } | 2470 | } |
2485 | 2471 | ||
2486 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 2472 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
2487 | { | 2473 | { |
2488 | return -EOPNOTSUPP; | 2474 | return -EOPNOTSUPP; |
2489 | } | 2475 | } |
2490 | 2476 | ||
2491 | static inline int security_secctx_to_secid(const char *secdata, | 2477 | static inline int security_secctx_to_secid(const char *secdata, |
2492 | u32 seclen, | 2478 | u32 seclen, |
2493 | u32 *secid) | 2479 | u32 *secid) |
2494 | { | 2480 | { |
2495 | return -EOPNOTSUPP; | 2481 | return -EOPNOTSUPP; |
2496 | } | 2482 | } |
2497 | 2483 | ||
2498 | static inline void security_release_secctx(char *secdata, u32 seclen) | 2484 | static inline void security_release_secctx(char *secdata, u32 seclen) |
2499 | { | 2485 | { |
2500 | } | 2486 | } |
2501 | 2487 | ||
2502 | static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | 2488 | static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) |
2503 | { | 2489 | { |
2504 | return -EOPNOTSUPP; | 2490 | return -EOPNOTSUPP; |
2505 | } | 2491 | } |
2506 | static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | 2492 | static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) |
2507 | { | 2493 | { |
2508 | return -EOPNOTSUPP; | 2494 | return -EOPNOTSUPP; |
2509 | } | 2495 | } |
2510 | static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | 2496 | static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) |
2511 | { | 2497 | { |
2512 | return -EOPNOTSUPP; | 2498 | return -EOPNOTSUPP; |
2513 | } | 2499 | } |
2514 | #endif /* CONFIG_SECURITY */ | 2500 | #endif /* CONFIG_SECURITY */ |
2515 | 2501 | ||
2516 | #ifdef CONFIG_SECURITY_NETWORK | 2502 | #ifdef CONFIG_SECURITY_NETWORK |
2517 | 2503 | ||
2518 | int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk); | 2504 | int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk); |
2519 | int security_unix_may_send(struct socket *sock, struct socket *other); | 2505 | int security_unix_may_send(struct socket *sock, struct socket *other); |
2520 | int security_socket_create(int family, int type, int protocol, int kern); | 2506 | int security_socket_create(int family, int type, int protocol, int kern); |
2521 | int security_socket_post_create(struct socket *sock, int family, | 2507 | int security_socket_post_create(struct socket *sock, int family, |
2522 | int type, int protocol, int kern); | 2508 | int type, int protocol, int kern); |
2523 | int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen); | 2509 | int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen); |
2524 | int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen); | 2510 | int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen); |
2525 | int security_socket_listen(struct socket *sock, int backlog); | 2511 | int security_socket_listen(struct socket *sock, int backlog); |
2526 | int security_socket_accept(struct socket *sock, struct socket *newsock); | 2512 | int security_socket_accept(struct socket *sock, struct socket *newsock); |
2527 | int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size); | 2513 | int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size); |
2528 | int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 2514 | int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
2529 | int size, int flags); | 2515 | int size, int flags); |
2530 | int security_socket_getsockname(struct socket *sock); | 2516 | int security_socket_getsockname(struct socket *sock); |
2531 | int security_socket_getpeername(struct socket *sock); | 2517 | int security_socket_getpeername(struct socket *sock); |
2532 | int security_socket_getsockopt(struct socket *sock, int level, int optname); | 2518 | int security_socket_getsockopt(struct socket *sock, int level, int optname); |
2533 | int security_socket_setsockopt(struct socket *sock, int level, int optname); | 2519 | int security_socket_setsockopt(struct socket *sock, int level, int optname); |
2534 | int security_socket_shutdown(struct socket *sock, int how); | 2520 | int security_socket_shutdown(struct socket *sock, int how); |
2535 | int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb); | 2521 | int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb); |
2536 | int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, | 2522 | int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
2537 | int __user *optlen, unsigned len); | 2523 | int __user *optlen, unsigned len); |
2538 | int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid); | 2524 | int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid); |
2539 | int security_sk_alloc(struct sock *sk, int family, gfp_t priority); | 2525 | int security_sk_alloc(struct sock *sk, int family, gfp_t priority); |
2540 | void security_sk_free(struct sock *sk); | 2526 | void security_sk_free(struct sock *sk); |
2541 | void security_sk_clone(const struct sock *sk, struct sock *newsk); | 2527 | void security_sk_clone(const struct sock *sk, struct sock *newsk); |
2542 | void security_sk_classify_flow(struct sock *sk, struct flowi *fl); | 2528 | void security_sk_classify_flow(struct sock *sk, struct flowi *fl); |
2543 | void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); | 2529 | void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); |
2544 | void security_sock_graft(struct sock*sk, struct socket *parent); | 2530 | void security_sock_graft(struct sock*sk, struct socket *parent); |
2545 | int security_inet_conn_request(struct sock *sk, | 2531 | int security_inet_conn_request(struct sock *sk, |
2546 | struct sk_buff *skb, struct request_sock *req); | 2532 | struct sk_buff *skb, struct request_sock *req); |
2547 | void security_inet_csk_clone(struct sock *newsk, | 2533 | void security_inet_csk_clone(struct sock *newsk, |
2548 | const struct request_sock *req); | 2534 | const struct request_sock *req); |
2549 | void security_inet_conn_established(struct sock *sk, | 2535 | void security_inet_conn_established(struct sock *sk, |
2550 | struct sk_buff *skb); | 2536 | struct sk_buff *skb); |
2551 | int security_secmark_relabel_packet(u32 secid); | 2537 | int security_secmark_relabel_packet(u32 secid); |
2552 | void security_secmark_refcount_inc(void); | 2538 | void security_secmark_refcount_inc(void); |
2553 | void security_secmark_refcount_dec(void); | 2539 | void security_secmark_refcount_dec(void); |
2554 | int security_tun_dev_create(void); | 2540 | int security_tun_dev_create(void); |
2555 | void security_tun_dev_post_create(struct sock *sk); | 2541 | void security_tun_dev_post_create(struct sock *sk); |
2556 | int security_tun_dev_attach(struct sock *sk); | 2542 | int security_tun_dev_attach(struct sock *sk); |
2557 | 2543 | ||
2558 | #else /* CONFIG_SECURITY_NETWORK */ | 2544 | #else /* CONFIG_SECURITY_NETWORK */ |
2559 | static inline int security_unix_stream_connect(struct sock *sock, | 2545 | static inline int security_unix_stream_connect(struct sock *sock, |
2560 | struct sock *other, | 2546 | struct sock *other, |
2561 | struct sock *newsk) | 2547 | struct sock *newsk) |
2562 | { | 2548 | { |
2563 | return 0; | 2549 | return 0; |
2564 | } | 2550 | } |
2565 | 2551 | ||
2566 | static inline int security_unix_may_send(struct socket *sock, | 2552 | static inline int security_unix_may_send(struct socket *sock, |
2567 | struct socket *other) | 2553 | struct socket *other) |
2568 | { | 2554 | { |
2569 | return 0; | 2555 | return 0; |
2570 | } | 2556 | } |
2571 | 2557 | ||
2572 | static inline int security_socket_create(int family, int type, | 2558 | static inline int security_socket_create(int family, int type, |
2573 | int protocol, int kern) | 2559 | int protocol, int kern) |
2574 | { | 2560 | { |
2575 | return 0; | 2561 | return 0; |
2576 | } | 2562 | } |
2577 | 2563 | ||
2578 | static inline int security_socket_post_create(struct socket *sock, | 2564 | static inline int security_socket_post_create(struct socket *sock, |
2579 | int family, | 2565 | int family, |
2580 | int type, | 2566 | int type, |
2581 | int protocol, int kern) | 2567 | int protocol, int kern) |
2582 | { | 2568 | { |
2583 | return 0; | 2569 | return 0; |
2584 | } | 2570 | } |
2585 | 2571 | ||
2586 | static inline int security_socket_bind(struct socket *sock, | 2572 | static inline int security_socket_bind(struct socket *sock, |
2587 | struct sockaddr *address, | 2573 | struct sockaddr *address, |
2588 | int addrlen) | 2574 | int addrlen) |
2589 | { | 2575 | { |
2590 | return 0; | 2576 | return 0; |
2591 | } | 2577 | } |
2592 | 2578 | ||
2593 | static inline int security_socket_connect(struct socket *sock, | 2579 | static inline int security_socket_connect(struct socket *sock, |
2594 | struct sockaddr *address, | 2580 | struct sockaddr *address, |
2595 | int addrlen) | 2581 | int addrlen) |
2596 | { | 2582 | { |
2597 | return 0; | 2583 | return 0; |
2598 | } | 2584 | } |
2599 | 2585 | ||
2600 | static inline int security_socket_listen(struct socket *sock, int backlog) | 2586 | static inline int security_socket_listen(struct socket *sock, int backlog) |
2601 | { | 2587 | { |
2602 | return 0; | 2588 | return 0; |
2603 | } | 2589 | } |
2604 | 2590 | ||
2605 | static inline int security_socket_accept(struct socket *sock, | 2591 | static inline int security_socket_accept(struct socket *sock, |
2606 | struct socket *newsock) | 2592 | struct socket *newsock) |
2607 | { | 2593 | { |
2608 | return 0; | 2594 | return 0; |
2609 | } | 2595 | } |
2610 | 2596 | ||
2611 | static inline int security_socket_sendmsg(struct socket *sock, | 2597 | static inline int security_socket_sendmsg(struct socket *sock, |
2612 | struct msghdr *msg, int size) | 2598 | struct msghdr *msg, int size) |
2613 | { | 2599 | { |
2614 | return 0; | 2600 | return 0; |
2615 | } | 2601 | } |
2616 | 2602 | ||
2617 | static inline int security_socket_recvmsg(struct socket *sock, | 2603 | static inline int security_socket_recvmsg(struct socket *sock, |
2618 | struct msghdr *msg, int size, | 2604 | struct msghdr *msg, int size, |
2619 | int flags) | 2605 | int flags) |
2620 | { | 2606 | { |
2621 | return 0; | 2607 | return 0; |
2622 | } | 2608 | } |
2623 | 2609 | ||
2624 | static inline int security_socket_getsockname(struct socket *sock) | 2610 | static inline int security_socket_getsockname(struct socket *sock) |
2625 | { | 2611 | { |
2626 | return 0; | 2612 | return 0; |
2627 | } | 2613 | } |
2628 | 2614 | ||
2629 | static inline int security_socket_getpeername(struct socket *sock) | 2615 | static inline int security_socket_getpeername(struct socket *sock) |
2630 | { | 2616 | { |
2631 | return 0; | 2617 | return 0; |
2632 | } | 2618 | } |
2633 | 2619 | ||
2634 | static inline int security_socket_getsockopt(struct socket *sock, | 2620 | static inline int security_socket_getsockopt(struct socket *sock, |
2635 | int level, int optname) | 2621 | int level, int optname) |
2636 | { | 2622 | { |
2637 | return 0; | 2623 | return 0; |
2638 | } | 2624 | } |
2639 | 2625 | ||
2640 | static inline int security_socket_setsockopt(struct socket *sock, | 2626 | static inline int security_socket_setsockopt(struct socket *sock, |
2641 | int level, int optname) | 2627 | int level, int optname) |
2642 | { | 2628 | { |
2643 | return 0; | 2629 | return 0; |
2644 | } | 2630 | } |
2645 | 2631 | ||
2646 | static inline int security_socket_shutdown(struct socket *sock, int how) | 2632 | static inline int security_socket_shutdown(struct socket *sock, int how) |
2647 | { | 2633 | { |
2648 | return 0; | 2634 | return 0; |
2649 | } | 2635 | } |
2650 | static inline int security_sock_rcv_skb(struct sock *sk, | 2636 | static inline int security_sock_rcv_skb(struct sock *sk, |
2651 | struct sk_buff *skb) | 2637 | struct sk_buff *skb) |
2652 | { | 2638 | { |
2653 | return 0; | 2639 | return 0; |
2654 | } | 2640 | } |
2655 | 2641 | ||
2656 | static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, | 2642 | static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
2657 | int __user *optlen, unsigned len) | 2643 | int __user *optlen, unsigned len) |
2658 | { | 2644 | { |
2659 | return -ENOPROTOOPT; | 2645 | return -ENOPROTOOPT; |
2660 | } | 2646 | } |
2661 | 2647 | ||
2662 | static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) | 2648 | static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) |
2663 | { | 2649 | { |
2664 | return -ENOPROTOOPT; | 2650 | return -ENOPROTOOPT; |
2665 | } | 2651 | } |
2666 | 2652 | ||
2667 | static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) | 2653 | static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) |
2668 | { | 2654 | { |
2669 | return 0; | 2655 | return 0; |
2670 | } | 2656 | } |
2671 | 2657 | ||
2672 | static inline void security_sk_free(struct sock *sk) | 2658 | static inline void security_sk_free(struct sock *sk) |
2673 | { | 2659 | { |
2674 | } | 2660 | } |
2675 | 2661 | ||
2676 | static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) | 2662 | static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) |
2677 | { | 2663 | { |
2678 | } | 2664 | } |
2679 | 2665 | ||
2680 | static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) | 2666 | static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) |
2681 | { | 2667 | { |
2682 | } | 2668 | } |
2683 | 2669 | ||
2684 | static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) | 2670 | static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) |
2685 | { | 2671 | { |
2686 | } | 2672 | } |
2687 | 2673 | ||
2688 | static inline void security_sock_graft(struct sock *sk, struct socket *parent) | 2674 | static inline void security_sock_graft(struct sock *sk, struct socket *parent) |
2689 | { | 2675 | { |
2690 | } | 2676 | } |
2691 | 2677 | ||
2692 | static inline int security_inet_conn_request(struct sock *sk, | 2678 | static inline int security_inet_conn_request(struct sock *sk, |
2693 | struct sk_buff *skb, struct request_sock *req) | 2679 | struct sk_buff *skb, struct request_sock *req) |
2694 | { | 2680 | { |
2695 | return 0; | 2681 | return 0; |
2696 | } | 2682 | } |
2697 | 2683 | ||
2698 | static inline void security_inet_csk_clone(struct sock *newsk, | 2684 | static inline void security_inet_csk_clone(struct sock *newsk, |
2699 | const struct request_sock *req) | 2685 | const struct request_sock *req) |
2700 | { | 2686 | { |
2701 | } | 2687 | } |
2702 | 2688 | ||
2703 | static inline void security_inet_conn_established(struct sock *sk, | 2689 | static inline void security_inet_conn_established(struct sock *sk, |
2704 | struct sk_buff *skb) | 2690 | struct sk_buff *skb) |
2705 | { | 2691 | { |
2706 | } | 2692 | } |
2707 | 2693 | ||
2708 | static inline int security_secmark_relabel_packet(u32 secid) | 2694 | static inline int security_secmark_relabel_packet(u32 secid) |
2709 | { | 2695 | { |
2710 | return 0; | 2696 | return 0; |
2711 | } | 2697 | } |
2712 | 2698 | ||
2713 | static inline void security_secmark_refcount_inc(void) | 2699 | static inline void security_secmark_refcount_inc(void) |
2714 | { | 2700 | { |
2715 | } | 2701 | } |
2716 | 2702 | ||
2717 | static inline void security_secmark_refcount_dec(void) | 2703 | static inline void security_secmark_refcount_dec(void) |
2718 | { | 2704 | { |
2719 | } | 2705 | } |
2720 | 2706 | ||
2721 | static inline int security_tun_dev_create(void) | 2707 | static inline int security_tun_dev_create(void) |
2722 | { | 2708 | { |
2723 | return 0; | 2709 | return 0; |
2724 | } | 2710 | } |
2725 | 2711 | ||
2726 | static inline void security_tun_dev_post_create(struct sock *sk) | 2712 | static inline void security_tun_dev_post_create(struct sock *sk) |
2727 | { | 2713 | { |
2728 | } | 2714 | } |
2729 | 2715 | ||
2730 | static inline int security_tun_dev_attach(struct sock *sk) | 2716 | static inline int security_tun_dev_attach(struct sock *sk) |
2731 | { | 2717 | { |
2732 | return 0; | 2718 | return 0; |
2733 | } | 2719 | } |
2734 | #endif /* CONFIG_SECURITY_NETWORK */ | 2720 | #endif /* CONFIG_SECURITY_NETWORK */ |
2735 | 2721 | ||
2736 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 2722 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
2737 | 2723 | ||
2738 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx); | 2724 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx); |
2739 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp); | 2725 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp); |
2740 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx); | 2726 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx); |
2741 | int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); | 2727 | int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); |
2742 | int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); | 2728 | int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); |
2743 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | 2729 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, |
2744 | struct xfrm_sec_ctx *polsec, u32 secid); | 2730 | struct xfrm_sec_ctx *polsec, u32 secid); |
2745 | int security_xfrm_state_delete(struct xfrm_state *x); | 2731 | int security_xfrm_state_delete(struct xfrm_state *x); |
2746 | void security_xfrm_state_free(struct xfrm_state *x); | 2732 | void security_xfrm_state_free(struct xfrm_state *x); |
2747 | int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); | 2733 | int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); |
2748 | int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | 2734 | int security_xfrm_state_pol_flow_match(struct xfrm_state *x, |
2749 | struct xfrm_policy *xp, | 2735 | struct xfrm_policy *xp, |
2750 | const struct flowi *fl); | 2736 | const struct flowi *fl); |
2751 | int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid); | 2737 | int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid); |
2752 | void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl); | 2738 | void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl); |
2753 | 2739 | ||
2754 | #else /* CONFIG_SECURITY_NETWORK_XFRM */ | 2740 | #else /* CONFIG_SECURITY_NETWORK_XFRM */ |
2755 | 2741 | ||
2756 | static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) | 2742 | static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) |
2757 | { | 2743 | { |
2758 | return 0; | 2744 | return 0; |
2759 | } | 2745 | } |
2760 | 2746 | ||
2761 | static inline int security_xfrm_policy_clone(struct xfrm_sec_ctx *old, struct xfrm_sec_ctx **new_ctxp) | 2747 | static inline int security_xfrm_policy_clone(struct xfrm_sec_ctx *old, struct xfrm_sec_ctx **new_ctxp) |
2762 | { | 2748 | { |
2763 | return 0; | 2749 | return 0; |
2764 | } | 2750 | } |
2765 | 2751 | ||
2766 | static inline void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx) | 2752 | static inline void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx) |
2767 | { | 2753 | { |
2768 | } | 2754 | } |
2769 | 2755 | ||
2770 | static inline int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) | 2756 | static inline int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) |
2771 | { | 2757 | { |
2772 | return 0; | 2758 | return 0; |
2773 | } | 2759 | } |
2774 | 2760 | ||
2775 | static inline int security_xfrm_state_alloc(struct xfrm_state *x, | 2761 | static inline int security_xfrm_state_alloc(struct xfrm_state *x, |
2776 | struct xfrm_user_sec_ctx *sec_ctx) | 2762 | struct xfrm_user_sec_ctx *sec_ctx) |
2777 | { | 2763 | { |
2778 | return 0; | 2764 | return 0; |
2779 | } | 2765 | } |
2780 | 2766 | ||
2781 | static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | 2767 | static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, |
2782 | struct xfrm_sec_ctx *polsec, u32 secid) | 2768 | struct xfrm_sec_ctx *polsec, u32 secid) |
2783 | { | 2769 | { |
2784 | return 0; | 2770 | return 0; |
2785 | } | 2771 | } |
2786 | 2772 | ||
2787 | static inline void security_xfrm_state_free(struct xfrm_state *x) | 2773 | static inline void security_xfrm_state_free(struct xfrm_state *x) |
2788 | { | 2774 | { |
2789 | } | 2775 | } |
2790 | 2776 | ||
2791 | static inline int security_xfrm_state_delete(struct xfrm_state *x) | 2777 | static inline int security_xfrm_state_delete(struct xfrm_state *x) |
2792 | { | 2778 | { |
2793 | return 0; | 2779 | return 0; |
2794 | } | 2780 | } |
2795 | 2781 | ||
2796 | static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) | 2782 | static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) |
2797 | { | 2783 | { |
2798 | return 0; | 2784 | return 0; |
2799 | } | 2785 | } |
2800 | 2786 | ||
2801 | static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | 2787 | static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, |
2802 | struct xfrm_policy *xp, const struct flowi *fl) | 2788 | struct xfrm_policy *xp, const struct flowi *fl) |
2803 | { | 2789 | { |
2804 | return 1; | 2790 | return 1; |
2805 | } | 2791 | } |
2806 | 2792 | ||
2807 | static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) | 2793 | static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) |
2808 | { | 2794 | { |
2809 | return 0; | 2795 | return 0; |
2810 | } | 2796 | } |
2811 | 2797 | ||
2812 | static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) | 2798 | static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) |
2813 | { | 2799 | { |
2814 | } | 2800 | } |
2815 | 2801 | ||
2816 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 2802 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
2817 | 2803 | ||
2818 | #ifdef CONFIG_SECURITY_PATH | 2804 | #ifdef CONFIG_SECURITY_PATH |
2819 | int security_path_unlink(struct path *dir, struct dentry *dentry); | 2805 | int security_path_unlink(struct path *dir, struct dentry *dentry); |
2820 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); | 2806 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); |
2821 | int security_path_rmdir(struct path *dir, struct dentry *dentry); | 2807 | int security_path_rmdir(struct path *dir, struct dentry *dentry); |
2822 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, | 2808 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, |
2823 | unsigned int dev); | 2809 | unsigned int dev); |
2824 | int security_path_truncate(struct path *path); | 2810 | int security_path_truncate(struct path *path); |
2825 | int security_path_symlink(struct path *dir, struct dentry *dentry, | 2811 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
2826 | const char *old_name); | 2812 | const char *old_name); |
2827 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | 2813 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, |
2828 | struct dentry *new_dentry); | 2814 | struct dentry *new_dentry); |
2829 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | 2815 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, |
2830 | struct path *new_dir, struct dentry *new_dentry); | 2816 | struct path *new_dir, struct dentry *new_dentry); |
2831 | int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | 2817 | int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, |
2832 | mode_t mode); | 2818 | mode_t mode); |
2833 | int security_path_chown(struct path *path, uid_t uid, gid_t gid); | 2819 | int security_path_chown(struct path *path, uid_t uid, gid_t gid); |
2834 | int security_path_chroot(struct path *path); | 2820 | int security_path_chroot(struct path *path); |
2835 | #else /* CONFIG_SECURITY_PATH */ | 2821 | #else /* CONFIG_SECURITY_PATH */ |
2836 | static inline int security_path_unlink(struct path *dir, struct dentry *dentry) | 2822 | static inline int security_path_unlink(struct path *dir, struct dentry *dentry) |
2837 | { | 2823 | { |
2838 | return 0; | 2824 | return 0; |
2839 | } | 2825 | } |
2840 | 2826 | ||
2841 | static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, | 2827 | static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, |
2842 | int mode) | 2828 | int mode) |
2843 | { | 2829 | { |
2844 | return 0; | 2830 | return 0; |
2845 | } | 2831 | } |
2846 | 2832 | ||
2847 | static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) | 2833 | static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) |
2848 | { | 2834 | { |
2849 | return 0; | 2835 | return 0; |
2850 | } | 2836 | } |
2851 | 2837 | ||
2852 | static inline int security_path_mknod(struct path *dir, struct dentry *dentry, | 2838 | static inline int security_path_mknod(struct path *dir, struct dentry *dentry, |
2853 | int mode, unsigned int dev) | 2839 | int mode, unsigned int dev) |
2854 | { | 2840 | { |
2855 | return 0; | 2841 | return 0; |
2856 | } | 2842 | } |
2857 | 2843 | ||
2858 | static inline int security_path_truncate(struct path *path) | 2844 | static inline int security_path_truncate(struct path *path) |
2859 | { | 2845 | { |
2860 | return 0; | 2846 | return 0; |
2861 | } | 2847 | } |
2862 | 2848 | ||
2863 | static inline int security_path_symlink(struct path *dir, struct dentry *dentry, | 2849 | static inline int security_path_symlink(struct path *dir, struct dentry *dentry, |
2864 | const char *old_name) | 2850 | const char *old_name) |
2865 | { | 2851 | { |
2866 | return 0; | 2852 | return 0; |
2867 | } | 2853 | } |
2868 | 2854 | ||
2869 | static inline int security_path_link(struct dentry *old_dentry, | 2855 | static inline int security_path_link(struct dentry *old_dentry, |
2870 | struct path *new_dir, | 2856 | struct path *new_dir, |
2871 | struct dentry *new_dentry) | 2857 | struct dentry *new_dentry) |
2872 | { | 2858 | { |
2873 | return 0; | 2859 | return 0; |
2874 | } | 2860 | } |
2875 | 2861 | ||
2876 | static inline int security_path_rename(struct path *old_dir, | 2862 | static inline int security_path_rename(struct path *old_dir, |
2877 | struct dentry *old_dentry, | 2863 | struct dentry *old_dentry, |
2878 | struct path *new_dir, | 2864 | struct path *new_dir, |
2879 | struct dentry *new_dentry) | 2865 | struct dentry *new_dentry) |
2880 | { | 2866 | { |
2881 | return 0; | 2867 | return 0; |
2882 | } | 2868 | } |
2883 | 2869 | ||
2884 | static inline int security_path_chmod(struct dentry *dentry, | 2870 | static inline int security_path_chmod(struct dentry *dentry, |
2885 | struct vfsmount *mnt, | 2871 | struct vfsmount *mnt, |
2886 | mode_t mode) | 2872 | mode_t mode) |
2887 | { | 2873 | { |
2888 | return 0; | 2874 | return 0; |
2889 | } | 2875 | } |
2890 | 2876 | ||
2891 | static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid) | 2877 | static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid) |
2892 | { | 2878 | { |
2893 | return 0; | 2879 | return 0; |
2894 | } | 2880 | } |
2895 | 2881 | ||
2896 | static inline int security_path_chroot(struct path *path) | 2882 | static inline int security_path_chroot(struct path *path) |
2897 | { | 2883 | { |
2898 | return 0; | 2884 | return 0; |
2899 | } | 2885 | } |
2900 | #endif /* CONFIG_SECURITY_PATH */ | 2886 | #endif /* CONFIG_SECURITY_PATH */ |
2901 | 2887 | ||
2902 | #ifdef CONFIG_KEYS | 2888 | #ifdef CONFIG_KEYS |
2903 | #ifdef CONFIG_SECURITY | 2889 | #ifdef CONFIG_SECURITY |
2904 | 2890 | ||
2905 | int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags); | 2891 | int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags); |
2906 | void security_key_free(struct key *key); | 2892 | void security_key_free(struct key *key); |
2907 | int security_key_permission(key_ref_t key_ref, | 2893 | int security_key_permission(key_ref_t key_ref, |
2908 | const struct cred *cred, key_perm_t perm); | 2894 | const struct cred *cred, key_perm_t perm); |
2909 | int security_key_getsecurity(struct key *key, char **_buffer); | 2895 | int security_key_getsecurity(struct key *key, char **_buffer); |
2910 | 2896 | ||
2911 | #else | 2897 | #else |
2912 | 2898 | ||
2913 | static inline int security_key_alloc(struct key *key, | 2899 | static inline int security_key_alloc(struct key *key, |
2914 | const struct cred *cred, | 2900 | const struct cred *cred, |
2915 | unsigned long flags) | 2901 | unsigned long flags) |
2916 | { | 2902 | { |
2917 | return 0; | 2903 | return 0; |
2918 | } | 2904 | } |
2919 | 2905 | ||
2920 | static inline void security_key_free(struct key *key) | 2906 | static inline void security_key_free(struct key *key) |
2921 | { | 2907 | { |
2922 | } | 2908 | } |
2923 | 2909 | ||
2924 | static inline int security_key_permission(key_ref_t key_ref, | 2910 | static inline int security_key_permission(key_ref_t key_ref, |
2925 | const struct cred *cred, | 2911 | const struct cred *cred, |
2926 | key_perm_t perm) | 2912 | key_perm_t perm) |
2927 | { | 2913 | { |
2928 | return 0; | 2914 | return 0; |
2929 | } | 2915 | } |
2930 | 2916 | ||
2931 | static inline int security_key_getsecurity(struct key *key, char **_buffer) | 2917 | static inline int security_key_getsecurity(struct key *key, char **_buffer) |
2932 | { | 2918 | { |
2933 | *_buffer = NULL; | 2919 | *_buffer = NULL; |
2934 | return 0; | 2920 | return 0; |
2935 | } | 2921 | } |
2936 | 2922 | ||
2937 | #endif | 2923 | #endif |
2938 | #endif /* CONFIG_KEYS */ | 2924 | #endif /* CONFIG_KEYS */ |
2939 | 2925 | ||
2940 | #ifdef CONFIG_AUDIT | 2926 | #ifdef CONFIG_AUDIT |
2941 | #ifdef CONFIG_SECURITY | 2927 | #ifdef CONFIG_SECURITY |
2942 | int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule); | 2928 | int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule); |
2943 | int security_audit_rule_known(struct audit_krule *krule); | 2929 | int security_audit_rule_known(struct audit_krule *krule); |
2944 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, | 2930 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, |
2945 | struct audit_context *actx); | 2931 | struct audit_context *actx); |
2946 | void security_audit_rule_free(void *lsmrule); | 2932 | void security_audit_rule_free(void *lsmrule); |
2947 | 2933 | ||
2948 | #else | 2934 | #else |
2949 | 2935 | ||
2950 | static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr, | 2936 | static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr, |
2951 | void **lsmrule) | 2937 | void **lsmrule) |
2952 | { | 2938 | { |
2953 | return 0; | 2939 | return 0; |
2954 | } | 2940 | } |
2955 | 2941 | ||
2956 | static inline int security_audit_rule_known(struct audit_krule *krule) | 2942 | static inline int security_audit_rule_known(struct audit_krule *krule) |
2957 | { | 2943 | { |
2958 | return 0; | 2944 | return 0; |
2959 | } | 2945 | } |
2960 | 2946 | ||
2961 | static inline int security_audit_rule_match(u32 secid, u32 field, u32 op, | 2947 | static inline int security_audit_rule_match(u32 secid, u32 field, u32 op, |
2962 | void *lsmrule, struct audit_context *actx) | 2948 | void *lsmrule, struct audit_context *actx) |
2963 | { | 2949 | { |
2964 | return 0; | 2950 | return 0; |
2965 | } | 2951 | } |
2966 | 2952 | ||
2967 | static inline void security_audit_rule_free(void *lsmrule) | 2953 | static inline void security_audit_rule_free(void *lsmrule) |
2968 | { } | 2954 | { } |
2969 | 2955 | ||
2970 | #endif /* CONFIG_SECURITY */ | 2956 | #endif /* CONFIG_SECURITY */ |
2971 | #endif /* CONFIG_AUDIT */ | 2957 | #endif /* CONFIG_AUDIT */ |
2972 | 2958 | ||
2973 | #ifdef CONFIG_SECURITYFS | 2959 | #ifdef CONFIG_SECURITYFS |
2974 | 2960 | ||
2975 | extern struct dentry *securityfs_create_file(const char *name, mode_t mode, | 2961 | extern struct dentry *securityfs_create_file(const char *name, mode_t mode, |
2976 | struct dentry *parent, void *data, | 2962 | struct dentry *parent, void *data, |
2977 | const struct file_operations *fops); | 2963 | const struct file_operations *fops); |
2978 | extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); | 2964 | extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); |
2979 | extern void securityfs_remove(struct dentry *dentry); | 2965 | extern void securityfs_remove(struct dentry *dentry); |
2980 | 2966 | ||
2981 | #else /* CONFIG_SECURITYFS */ | 2967 | #else /* CONFIG_SECURITYFS */ |
2982 | 2968 | ||
2983 | static inline struct dentry *securityfs_create_dir(const char *name, | 2969 | static inline struct dentry *securityfs_create_dir(const char *name, |
2984 | struct dentry *parent) | 2970 | struct dentry *parent) |
2985 | { | 2971 | { |
2986 | return ERR_PTR(-ENODEV); | 2972 | return ERR_PTR(-ENODEV); |
2987 | } | 2973 | } |
2988 | 2974 | ||
2989 | static inline struct dentry *securityfs_create_file(const char *name, | 2975 | static inline struct dentry *securityfs_create_file(const char *name, |
2990 | mode_t mode, | 2976 | mode_t mode, |
2991 | struct dentry *parent, | 2977 | struct dentry *parent, |
2992 | void *data, | 2978 | void *data, |
2993 | const struct file_operations *fops) | 2979 | const struct file_operations *fops) |
2994 | { | 2980 | { |
2995 | return ERR_PTR(-ENODEV); | 2981 | return ERR_PTR(-ENODEV); |
2996 | } | 2982 | } |
2997 | 2983 | ||
2998 | static inline void securityfs_remove(struct dentry *dentry) | 2984 | static inline void securityfs_remove(struct dentry *dentry) |
2999 | {} | 2985 | {} |
3000 | 2986 | ||
3001 | #endif | 2987 | #endif |
3002 | 2988 | ||
3003 | #ifdef CONFIG_SECURITY | 2989 | #ifdef CONFIG_SECURITY |
3004 | 2990 | ||
3005 | static inline char *alloc_secdata(void) | 2991 | static inline char *alloc_secdata(void) |
3006 | { | 2992 | { |
3007 | return (char *)get_zeroed_page(GFP_KERNEL); | 2993 | return (char *)get_zeroed_page(GFP_KERNEL); |
3008 | } | 2994 | } |
3009 | 2995 | ||
3010 | static inline void free_secdata(void *secdata) | 2996 | static inline void free_secdata(void *secdata) |
3011 | { | 2997 | { |
3012 | free_page((unsigned long)secdata); | 2998 | free_page((unsigned long)secdata); |
3013 | } | 2999 | } |
3014 | 3000 | ||
3015 | #else | 3001 | #else |
3016 | 3002 | ||
3017 | static inline char *alloc_secdata(void) | 3003 | static inline char *alloc_secdata(void) |
3018 | { | 3004 | { |
3019 | return (char *)1; | 3005 | return (char *)1; |
3020 | } | 3006 | } |
3021 | 3007 | ||
3022 | static inline void free_secdata(void *secdata) | 3008 | static inline void free_secdata(void *secdata) |
3023 | { } | 3009 | { } |
3024 | #endif /* CONFIG_SECURITY */ | 3010 | #endif /* CONFIG_SECURITY */ |
3025 | 3011 | ||
3026 | #endif /* ! __LINUX_SECURITY_H */ | 3012 | #endif /* ! __LINUX_SECURITY_H */ |
3027 | 3013 | ||
3028 | 3014 |
kernel/audit.c
1 | /* audit.c -- Auditing support | 1 | /* audit.c -- Auditing support |
2 | * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. | 2 | * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. |
3 | * System-call specific features have moved to auditsc.c | 3 | * System-call specific features have moved to auditsc.c |
4 | * | 4 | * |
5 | * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina. | 5 | * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina. |
6 | * All Rights Reserved. | 6 | * All Rights Reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | * | 21 | * |
22 | * Written by Rickard E. (Rik) Faith <faith@redhat.com> | 22 | * Written by Rickard E. (Rik) Faith <faith@redhat.com> |
23 | * | 23 | * |
24 | * Goals: 1) Integrate fully with Security Modules. | 24 | * Goals: 1) Integrate fully with Security Modules. |
25 | * 2) Minimal run-time overhead: | 25 | * 2) Minimal run-time overhead: |
26 | * a) Minimal when syscall auditing is disabled (audit_enable=0). | 26 | * a) Minimal when syscall auditing is disabled (audit_enable=0). |
27 | * b) Small when syscall auditing is enabled and no audit record | 27 | * b) Small when syscall auditing is enabled and no audit record |
28 | * is generated (defer as much work as possible to record | 28 | * is generated (defer as much work as possible to record |
29 | * generation time): | 29 | * generation time): |
30 | * i) context is allocated, | 30 | * i) context is allocated, |
31 | * ii) names from getname are stored without a copy, and | 31 | * ii) names from getname are stored without a copy, and |
32 | * iii) inode information stored from path_lookup. | 32 | * iii) inode information stored from path_lookup. |
33 | * 3) Ability to disable syscall auditing at boot time (audit=0). | 33 | * 3) Ability to disable syscall auditing at boot time (audit=0). |
34 | * 4) Usable by other parts of the kernel (if audit_log* is called, | 34 | * 4) Usable by other parts of the kernel (if audit_log* is called, |
35 | * then a syscall record will be generated automatically for the | 35 | * then a syscall record will be generated automatically for the |
36 | * current syscall). | 36 | * current syscall). |
37 | * 5) Netlink interface to user-space. | 37 | * 5) Netlink interface to user-space. |
38 | * 6) Support low-overhead kernel-based filtering to minimize the | 38 | * 6) Support low-overhead kernel-based filtering to minimize the |
39 | * information that must be passed to user-space. | 39 | * information that must be passed to user-space. |
40 | * | 40 | * |
41 | * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ | 41 | * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ |
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
45 | #include <asm/types.h> | 45 | #include <asm/types.h> |
46 | #include <linux/atomic.h> | 46 | #include <linux/atomic.h> |
47 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
48 | #include <linux/module.h> | 48 | #include <linux/module.h> |
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
51 | #include <linux/kthread.h> | 51 | #include <linux/kthread.h> |
52 | 52 | ||
53 | #include <linux/audit.h> | 53 | #include <linux/audit.h> |
54 | 54 | ||
55 | #include <net/sock.h> | 55 | #include <net/sock.h> |
56 | #include <net/netlink.h> | 56 | #include <net/netlink.h> |
57 | #include <linux/skbuff.h> | 57 | #include <linux/skbuff.h> |
58 | #ifdef CONFIG_SECURITY | 58 | #ifdef CONFIG_SECURITY |
59 | #include <linux/security.h> | 59 | #include <linux/security.h> |
60 | #endif | 60 | #endif |
61 | #include <linux/netlink.h> | 61 | #include <linux/netlink.h> |
62 | #include <linux/freezer.h> | 62 | #include <linux/freezer.h> |
63 | #include <linux/tty.h> | 63 | #include <linux/tty.h> |
64 | 64 | ||
65 | #include "audit.h" | 65 | #include "audit.h" |
66 | 66 | ||
67 | /* No auditing will take place until audit_initialized == AUDIT_INITIALIZED. | 67 | /* No auditing will take place until audit_initialized == AUDIT_INITIALIZED. |
68 | * (Initialization happens after skb_init is called.) */ | 68 | * (Initialization happens after skb_init is called.) */ |
69 | #define AUDIT_DISABLED -1 | 69 | #define AUDIT_DISABLED -1 |
70 | #define AUDIT_UNINITIALIZED 0 | 70 | #define AUDIT_UNINITIALIZED 0 |
71 | #define AUDIT_INITIALIZED 1 | 71 | #define AUDIT_INITIALIZED 1 |
72 | static int audit_initialized; | 72 | static int audit_initialized; |
73 | 73 | ||
74 | #define AUDIT_OFF 0 | 74 | #define AUDIT_OFF 0 |
75 | #define AUDIT_ON 1 | 75 | #define AUDIT_ON 1 |
76 | #define AUDIT_LOCKED 2 | 76 | #define AUDIT_LOCKED 2 |
77 | int audit_enabled; | 77 | int audit_enabled; |
78 | int audit_ever_enabled; | 78 | int audit_ever_enabled; |
79 | 79 | ||
80 | EXPORT_SYMBOL_GPL(audit_enabled); | 80 | EXPORT_SYMBOL_GPL(audit_enabled); |
81 | 81 | ||
82 | /* Default state when kernel boots without any parameters. */ | 82 | /* Default state when kernel boots without any parameters. */ |
83 | static int audit_default; | 83 | static int audit_default; |
84 | 84 | ||
85 | /* If auditing cannot proceed, audit_failure selects what happens. */ | 85 | /* If auditing cannot proceed, audit_failure selects what happens. */ |
86 | static int audit_failure = AUDIT_FAIL_PRINTK; | 86 | static int audit_failure = AUDIT_FAIL_PRINTK; |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * If audit records are to be written to the netlink socket, audit_pid | 89 | * If audit records are to be written to the netlink socket, audit_pid |
90 | * contains the pid of the auditd process and audit_nlk_pid contains | 90 | * contains the pid of the auditd process and audit_nlk_pid contains |
91 | * the pid to use to send netlink messages to that process. | 91 | * the pid to use to send netlink messages to that process. |
92 | */ | 92 | */ |
93 | int audit_pid; | 93 | int audit_pid; |
94 | static int audit_nlk_pid; | 94 | static int audit_nlk_pid; |
95 | 95 | ||
96 | /* If audit_rate_limit is non-zero, limit the rate of sending audit records | 96 | /* If audit_rate_limit is non-zero, limit the rate of sending audit records |
97 | * to that number per second. This prevents DoS attacks, but results in | 97 | * to that number per second. This prevents DoS attacks, but results in |
98 | * audit records being dropped. */ | 98 | * audit records being dropped. */ |
99 | static int audit_rate_limit; | 99 | static int audit_rate_limit; |
100 | 100 | ||
101 | /* Number of outstanding audit_buffers allowed. */ | 101 | /* Number of outstanding audit_buffers allowed. */ |
102 | static int audit_backlog_limit = 64; | 102 | static int audit_backlog_limit = 64; |
103 | static int audit_backlog_wait_time = 60 * HZ; | 103 | static int audit_backlog_wait_time = 60 * HZ; |
104 | static int audit_backlog_wait_overflow = 0; | 104 | static int audit_backlog_wait_overflow = 0; |
105 | 105 | ||
106 | /* The identity of the user shutting down the audit system. */ | 106 | /* The identity of the user shutting down the audit system. */ |
107 | uid_t audit_sig_uid = -1; | 107 | uid_t audit_sig_uid = -1; |
108 | pid_t audit_sig_pid = -1; | 108 | pid_t audit_sig_pid = -1; |
109 | u32 audit_sig_sid = 0; | 109 | u32 audit_sig_sid = 0; |
110 | 110 | ||
111 | /* Records can be lost in several ways: | 111 | /* Records can be lost in several ways: |
112 | 0) [suppressed in audit_alloc] | 112 | 0) [suppressed in audit_alloc] |
113 | 1) out of memory in audit_log_start [kmalloc of struct audit_buffer] | 113 | 1) out of memory in audit_log_start [kmalloc of struct audit_buffer] |
114 | 2) out of memory in audit_log_move [alloc_skb] | 114 | 2) out of memory in audit_log_move [alloc_skb] |
115 | 3) suppressed due to audit_rate_limit | 115 | 3) suppressed due to audit_rate_limit |
116 | 4) suppressed due to audit_backlog_limit | 116 | 4) suppressed due to audit_backlog_limit |
117 | */ | 117 | */ |
118 | static atomic_t audit_lost = ATOMIC_INIT(0); | 118 | static atomic_t audit_lost = ATOMIC_INIT(0); |
119 | 119 | ||
120 | /* The netlink socket. */ | 120 | /* The netlink socket. */ |
121 | static struct sock *audit_sock; | 121 | static struct sock *audit_sock; |
122 | 122 | ||
123 | /* Hash for inode-based rules */ | 123 | /* Hash for inode-based rules */ |
124 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; | 124 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; |
125 | 125 | ||
126 | /* The audit_freelist is a list of pre-allocated audit buffers (if more | 126 | /* The audit_freelist is a list of pre-allocated audit buffers (if more |
127 | * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of | 127 | * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of |
128 | * being placed on the freelist). */ | 128 | * being placed on the freelist). */ |
129 | static DEFINE_SPINLOCK(audit_freelist_lock); | 129 | static DEFINE_SPINLOCK(audit_freelist_lock); |
130 | static int audit_freelist_count; | 130 | static int audit_freelist_count; |
131 | static LIST_HEAD(audit_freelist); | 131 | static LIST_HEAD(audit_freelist); |
132 | 132 | ||
133 | static struct sk_buff_head audit_skb_queue; | 133 | static struct sk_buff_head audit_skb_queue; |
134 | /* queue of skbs to send to auditd when/if it comes back */ | 134 | /* queue of skbs to send to auditd when/if it comes back */ |
135 | static struct sk_buff_head audit_skb_hold_queue; | 135 | static struct sk_buff_head audit_skb_hold_queue; |
136 | static struct task_struct *kauditd_task; | 136 | static struct task_struct *kauditd_task; |
137 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 137 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
138 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 138 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
139 | 139 | ||
140 | /* Serialize requests from userspace. */ | 140 | /* Serialize requests from userspace. */ |
141 | DEFINE_MUTEX(audit_cmd_mutex); | 141 | DEFINE_MUTEX(audit_cmd_mutex); |
142 | 142 | ||
143 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting | 143 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting |
144 | * audit records. Since printk uses a 1024 byte buffer, this buffer | 144 | * audit records. Since printk uses a 1024 byte buffer, this buffer |
145 | * should be at least that large. */ | 145 | * should be at least that large. */ |
146 | #define AUDIT_BUFSIZ 1024 | 146 | #define AUDIT_BUFSIZ 1024 |
147 | 147 | ||
148 | /* AUDIT_MAXFREE is the number of empty audit_buffers we keep on the | 148 | /* AUDIT_MAXFREE is the number of empty audit_buffers we keep on the |
149 | * audit_freelist. Doing so eliminates many kmalloc/kfree calls. */ | 149 | * audit_freelist. Doing so eliminates many kmalloc/kfree calls. */ |
150 | #define AUDIT_MAXFREE (2*NR_CPUS) | 150 | #define AUDIT_MAXFREE (2*NR_CPUS) |
151 | 151 | ||
152 | /* The audit_buffer is used when formatting an audit record. The caller | 152 | /* The audit_buffer is used when formatting an audit record. The caller |
153 | * locks briefly to get the record off the freelist or to allocate the | 153 | * locks briefly to get the record off the freelist or to allocate the |
154 | * buffer, and locks briefly to send the buffer to the netlink layer or | 154 | * buffer, and locks briefly to send the buffer to the netlink layer or |
155 | * to place it on a transmit queue. Multiple audit_buffers can be in | 155 | * to place it on a transmit queue. Multiple audit_buffers can be in |
156 | * use simultaneously. */ | 156 | * use simultaneously. */ |
157 | struct audit_buffer { | 157 | struct audit_buffer { |
158 | struct list_head list; | 158 | struct list_head list; |
159 | struct sk_buff *skb; /* formatted skb ready to send */ | 159 | struct sk_buff *skb; /* formatted skb ready to send */ |
160 | struct audit_context *ctx; /* NULL or associated context */ | 160 | struct audit_context *ctx; /* NULL or associated context */ |
161 | gfp_t gfp_mask; | 161 | gfp_t gfp_mask; |
162 | }; | 162 | }; |
163 | 163 | ||
164 | struct audit_reply { | 164 | struct audit_reply { |
165 | int pid; | 165 | int pid; |
166 | struct sk_buff *skb; | 166 | struct sk_buff *skb; |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | 169 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) |
170 | { | 170 | { |
171 | if (ab) { | 171 | if (ab) { |
172 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 172 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
173 | nlh->nlmsg_pid = pid; | 173 | nlh->nlmsg_pid = pid; |
174 | } | 174 | } |
175 | } | 175 | } |
176 | 176 | ||
177 | void audit_panic(const char *message) | 177 | void audit_panic(const char *message) |
178 | { | 178 | { |
179 | switch (audit_failure) | 179 | switch (audit_failure) |
180 | { | 180 | { |
181 | case AUDIT_FAIL_SILENT: | 181 | case AUDIT_FAIL_SILENT: |
182 | break; | 182 | break; |
183 | case AUDIT_FAIL_PRINTK: | 183 | case AUDIT_FAIL_PRINTK: |
184 | if (printk_ratelimit()) | 184 | if (printk_ratelimit()) |
185 | printk(KERN_ERR "audit: %s\n", message); | 185 | printk(KERN_ERR "audit: %s\n", message); |
186 | break; | 186 | break; |
187 | case AUDIT_FAIL_PANIC: | 187 | case AUDIT_FAIL_PANIC: |
188 | /* test audit_pid since printk is always losey, why bother? */ | 188 | /* test audit_pid since printk is always losey, why bother? */ |
189 | if (audit_pid) | 189 | if (audit_pid) |
190 | panic("audit: %s\n", message); | 190 | panic("audit: %s\n", message); |
191 | break; | 191 | break; |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | static inline int audit_rate_check(void) | 195 | static inline int audit_rate_check(void) |
196 | { | 196 | { |
197 | static unsigned long last_check = 0; | 197 | static unsigned long last_check = 0; |
198 | static int messages = 0; | 198 | static int messages = 0; |
199 | static DEFINE_SPINLOCK(lock); | 199 | static DEFINE_SPINLOCK(lock); |
200 | unsigned long flags; | 200 | unsigned long flags; |
201 | unsigned long now; | 201 | unsigned long now; |
202 | unsigned long elapsed; | 202 | unsigned long elapsed; |
203 | int retval = 0; | 203 | int retval = 0; |
204 | 204 | ||
205 | if (!audit_rate_limit) return 1; | 205 | if (!audit_rate_limit) return 1; |
206 | 206 | ||
207 | spin_lock_irqsave(&lock, flags); | 207 | spin_lock_irqsave(&lock, flags); |
208 | if (++messages < audit_rate_limit) { | 208 | if (++messages < audit_rate_limit) { |
209 | retval = 1; | 209 | retval = 1; |
210 | } else { | 210 | } else { |
211 | now = jiffies; | 211 | now = jiffies; |
212 | elapsed = now - last_check; | 212 | elapsed = now - last_check; |
213 | if (elapsed > HZ) { | 213 | if (elapsed > HZ) { |
214 | last_check = now; | 214 | last_check = now; |
215 | messages = 0; | 215 | messages = 0; |
216 | retval = 1; | 216 | retval = 1; |
217 | } | 217 | } |
218 | } | 218 | } |
219 | spin_unlock_irqrestore(&lock, flags); | 219 | spin_unlock_irqrestore(&lock, flags); |
220 | 220 | ||
221 | return retval; | 221 | return retval; |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | 224 | /** |
225 | * audit_log_lost - conditionally log lost audit message event | 225 | * audit_log_lost - conditionally log lost audit message event |
226 | * @message: the message stating reason for lost audit message | 226 | * @message: the message stating reason for lost audit message |
227 | * | 227 | * |
228 | * Emit at least 1 message per second, even if audit_rate_check is | 228 | * Emit at least 1 message per second, even if audit_rate_check is |
229 | * throttling. | 229 | * throttling. |
230 | * Always increment the lost messages counter. | 230 | * Always increment the lost messages counter. |
231 | */ | 231 | */ |
232 | void audit_log_lost(const char *message) | 232 | void audit_log_lost(const char *message) |
233 | { | 233 | { |
234 | static unsigned long last_msg = 0; | 234 | static unsigned long last_msg = 0; |
235 | static DEFINE_SPINLOCK(lock); | 235 | static DEFINE_SPINLOCK(lock); |
236 | unsigned long flags; | 236 | unsigned long flags; |
237 | unsigned long now; | 237 | unsigned long now; |
238 | int print; | 238 | int print; |
239 | 239 | ||
240 | atomic_inc(&audit_lost); | 240 | atomic_inc(&audit_lost); |
241 | 241 | ||
242 | print = (audit_failure == AUDIT_FAIL_PANIC || !audit_rate_limit); | 242 | print = (audit_failure == AUDIT_FAIL_PANIC || !audit_rate_limit); |
243 | 243 | ||
244 | if (!print) { | 244 | if (!print) { |
245 | spin_lock_irqsave(&lock, flags); | 245 | spin_lock_irqsave(&lock, flags); |
246 | now = jiffies; | 246 | now = jiffies; |
247 | if (now - last_msg > HZ) { | 247 | if (now - last_msg > HZ) { |
248 | print = 1; | 248 | print = 1; |
249 | last_msg = now; | 249 | last_msg = now; |
250 | } | 250 | } |
251 | spin_unlock_irqrestore(&lock, flags); | 251 | spin_unlock_irqrestore(&lock, flags); |
252 | } | 252 | } |
253 | 253 | ||
254 | if (print) { | 254 | if (print) { |
255 | if (printk_ratelimit()) | 255 | if (printk_ratelimit()) |
256 | printk(KERN_WARNING | 256 | printk(KERN_WARNING |
257 | "audit: audit_lost=%d audit_rate_limit=%d " | 257 | "audit: audit_lost=%d audit_rate_limit=%d " |
258 | "audit_backlog_limit=%d\n", | 258 | "audit_backlog_limit=%d\n", |
259 | atomic_read(&audit_lost), | 259 | atomic_read(&audit_lost), |
260 | audit_rate_limit, | 260 | audit_rate_limit, |
261 | audit_backlog_limit); | 261 | audit_backlog_limit); |
262 | audit_panic(message); | 262 | audit_panic(message); |
263 | } | 263 | } |
264 | } | 264 | } |
265 | 265 | ||
266 | static int audit_log_config_change(char *function_name, int new, int old, | 266 | static int audit_log_config_change(char *function_name, int new, int old, |
267 | uid_t loginuid, u32 sessionid, u32 sid, | 267 | uid_t loginuid, u32 sessionid, u32 sid, |
268 | int allow_changes) | 268 | int allow_changes) |
269 | { | 269 | { |
270 | struct audit_buffer *ab; | 270 | struct audit_buffer *ab; |
271 | int rc = 0; | 271 | int rc = 0; |
272 | 272 | ||
273 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 273 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
274 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, | 274 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, |
275 | old, loginuid, sessionid); | 275 | old, loginuid, sessionid); |
276 | if (sid) { | 276 | if (sid) { |
277 | char *ctx = NULL; | 277 | char *ctx = NULL; |
278 | u32 len; | 278 | u32 len; |
279 | 279 | ||
280 | rc = security_secid_to_secctx(sid, &ctx, &len); | 280 | rc = security_secid_to_secctx(sid, &ctx, &len); |
281 | if (rc) { | 281 | if (rc) { |
282 | audit_log_format(ab, " sid=%u", sid); | 282 | audit_log_format(ab, " sid=%u", sid); |
283 | allow_changes = 0; /* Something weird, deny request */ | 283 | allow_changes = 0; /* Something weird, deny request */ |
284 | } else { | 284 | } else { |
285 | audit_log_format(ab, " subj=%s", ctx); | 285 | audit_log_format(ab, " subj=%s", ctx); |
286 | security_release_secctx(ctx, len); | 286 | security_release_secctx(ctx, len); |
287 | } | 287 | } |
288 | } | 288 | } |
289 | audit_log_format(ab, " res=%d", allow_changes); | 289 | audit_log_format(ab, " res=%d", allow_changes); |
290 | audit_log_end(ab); | 290 | audit_log_end(ab); |
291 | return rc; | 291 | return rc; |
292 | } | 292 | } |
293 | 293 | ||
294 | static int audit_do_config_change(char *function_name, int *to_change, | 294 | static int audit_do_config_change(char *function_name, int *to_change, |
295 | int new, uid_t loginuid, u32 sessionid, | 295 | int new, uid_t loginuid, u32 sessionid, |
296 | u32 sid) | 296 | u32 sid) |
297 | { | 297 | { |
298 | int allow_changes, rc = 0, old = *to_change; | 298 | int allow_changes, rc = 0, old = *to_change; |
299 | 299 | ||
300 | /* check if we are locked */ | 300 | /* check if we are locked */ |
301 | if (audit_enabled == AUDIT_LOCKED) | 301 | if (audit_enabled == AUDIT_LOCKED) |
302 | allow_changes = 0; | 302 | allow_changes = 0; |
303 | else | 303 | else |
304 | allow_changes = 1; | 304 | allow_changes = 1; |
305 | 305 | ||
306 | if (audit_enabled != AUDIT_OFF) { | 306 | if (audit_enabled != AUDIT_OFF) { |
307 | rc = audit_log_config_change(function_name, new, old, loginuid, | 307 | rc = audit_log_config_change(function_name, new, old, loginuid, |
308 | sessionid, sid, allow_changes); | 308 | sessionid, sid, allow_changes); |
309 | if (rc) | 309 | if (rc) |
310 | allow_changes = 0; | 310 | allow_changes = 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | /* If we are allowed, make the change */ | 313 | /* If we are allowed, make the change */ |
314 | if (allow_changes == 1) | 314 | if (allow_changes == 1) |
315 | *to_change = new; | 315 | *to_change = new; |
316 | /* Not allowed, update reason */ | 316 | /* Not allowed, update reason */ |
317 | else if (rc == 0) | 317 | else if (rc == 0) |
318 | rc = -EPERM; | 318 | rc = -EPERM; |
319 | return rc; | 319 | return rc; |
320 | } | 320 | } |
321 | 321 | ||
322 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid, | 322 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid, |
323 | u32 sid) | 323 | u32 sid) |
324 | { | 324 | { |
325 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | 325 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, |
326 | limit, loginuid, sessionid, sid); | 326 | limit, loginuid, sessionid, sid); |
327 | } | 327 | } |
328 | 328 | ||
329 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid, | 329 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid, |
330 | u32 sid) | 330 | u32 sid) |
331 | { | 331 | { |
332 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, | 332 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, |
333 | limit, loginuid, sessionid, sid); | 333 | limit, loginuid, sessionid, sid); |
334 | } | 334 | } |
335 | 335 | ||
336 | static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) | 336 | static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) |
337 | { | 337 | { |
338 | int rc; | 338 | int rc; |
339 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 339 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) |
340 | return -EINVAL; | 340 | return -EINVAL; |
341 | 341 | ||
342 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, | 342 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, |
343 | loginuid, sessionid, sid); | 343 | loginuid, sessionid, sid); |
344 | 344 | ||
345 | if (!rc) | 345 | if (!rc) |
346 | audit_ever_enabled |= !!state; | 346 | audit_ever_enabled |= !!state; |
347 | 347 | ||
348 | return rc; | 348 | return rc; |
349 | } | 349 | } |
350 | 350 | ||
351 | static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) | 351 | static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) |
352 | { | 352 | { |
353 | if (state != AUDIT_FAIL_SILENT | 353 | if (state != AUDIT_FAIL_SILENT |
354 | && state != AUDIT_FAIL_PRINTK | 354 | && state != AUDIT_FAIL_PRINTK |
355 | && state != AUDIT_FAIL_PANIC) | 355 | && state != AUDIT_FAIL_PANIC) |
356 | return -EINVAL; | 356 | return -EINVAL; |
357 | 357 | ||
358 | return audit_do_config_change("audit_failure", &audit_failure, state, | 358 | return audit_do_config_change("audit_failure", &audit_failure, state, |
359 | loginuid, sessionid, sid); | 359 | loginuid, sessionid, sid); |
360 | } | 360 | } |
361 | 361 | ||
362 | /* | 362 | /* |
363 | * Queue skbs to be sent to auditd when/if it comes back. These skbs should | 363 | * Queue skbs to be sent to auditd when/if it comes back. These skbs should |
364 | * already have been sent via prink/syslog and so if these messages are dropped | 364 | * already have been sent via prink/syslog and so if these messages are dropped |
365 | * it is not a huge concern since we already passed the audit_log_lost() | 365 | * it is not a huge concern since we already passed the audit_log_lost() |
366 | * notification and stuff. This is just nice to get audit messages during | 366 | * notification and stuff. This is just nice to get audit messages during |
367 | * boot before auditd is running or messages generated while auditd is stopped. | 367 | * boot before auditd is running or messages generated while auditd is stopped. |
368 | * This only holds messages is audit_default is set, aka booting with audit=1 | 368 | * This only holds messages is audit_default is set, aka booting with audit=1 |
369 | * or building your kernel that way. | 369 | * or building your kernel that way. |
370 | */ | 370 | */ |
371 | static void audit_hold_skb(struct sk_buff *skb) | 371 | static void audit_hold_skb(struct sk_buff *skb) |
372 | { | 372 | { |
373 | if (audit_default && | 373 | if (audit_default && |
374 | skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit) | 374 | skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit) |
375 | skb_queue_tail(&audit_skb_hold_queue, skb); | 375 | skb_queue_tail(&audit_skb_hold_queue, skb); |
376 | else | 376 | else |
377 | kfree_skb(skb); | 377 | kfree_skb(skb); |
378 | } | 378 | } |
379 | 379 | ||
380 | /* | 380 | /* |
381 | * For one reason or another this nlh isn't getting delivered to the userspace | 381 | * For one reason or another this nlh isn't getting delivered to the userspace |
382 | * audit daemon, just send it to printk. | 382 | * audit daemon, just send it to printk. |
383 | */ | 383 | */ |
384 | static void audit_printk_skb(struct sk_buff *skb) | 384 | static void audit_printk_skb(struct sk_buff *skb) |
385 | { | 385 | { |
386 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | 386 | struct nlmsghdr *nlh = nlmsg_hdr(skb); |
387 | char *data = NLMSG_DATA(nlh); | 387 | char *data = NLMSG_DATA(nlh); |
388 | 388 | ||
389 | if (nlh->nlmsg_type != AUDIT_EOE) { | 389 | if (nlh->nlmsg_type != AUDIT_EOE) { |
390 | if (printk_ratelimit()) | 390 | if (printk_ratelimit()) |
391 | printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); | 391 | printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); |
392 | else | 392 | else |
393 | audit_log_lost("printk limit exceeded\n"); | 393 | audit_log_lost("printk limit exceeded\n"); |
394 | } | 394 | } |
395 | 395 | ||
396 | audit_hold_skb(skb); | 396 | audit_hold_skb(skb); |
397 | } | 397 | } |
398 | 398 | ||
399 | static void kauditd_send_skb(struct sk_buff *skb) | 399 | static void kauditd_send_skb(struct sk_buff *skb) |
400 | { | 400 | { |
401 | int err; | 401 | int err; |
402 | /* take a reference in case we can't send it and we want to hold it */ | 402 | /* take a reference in case we can't send it and we want to hold it */ |
403 | skb_get(skb); | 403 | skb_get(skb); |
404 | err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0); | 404 | err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0); |
405 | if (err < 0) { | 405 | if (err < 0) { |
406 | BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ | 406 | BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ |
407 | printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); | 407 | printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); |
408 | audit_log_lost("auditd disappeared\n"); | 408 | audit_log_lost("auditd disappeared\n"); |
409 | audit_pid = 0; | 409 | audit_pid = 0; |
410 | /* we might get lucky and get this in the next auditd */ | 410 | /* we might get lucky and get this in the next auditd */ |
411 | audit_hold_skb(skb); | 411 | audit_hold_skb(skb); |
412 | } else | 412 | } else |
413 | /* drop the extra reference if sent ok */ | 413 | /* drop the extra reference if sent ok */ |
414 | consume_skb(skb); | 414 | consume_skb(skb); |
415 | } | 415 | } |
416 | 416 | ||
417 | static int kauditd_thread(void *dummy) | 417 | static int kauditd_thread(void *dummy) |
418 | { | 418 | { |
419 | struct sk_buff *skb; | 419 | struct sk_buff *skb; |
420 | 420 | ||
421 | set_freezable(); | 421 | set_freezable(); |
422 | while (!kthread_should_stop()) { | 422 | while (!kthread_should_stop()) { |
423 | /* | 423 | /* |
424 | * if auditd just started drain the queue of messages already | 424 | * if auditd just started drain the queue of messages already |
425 | * sent to syslog/printk. remember loss here is ok. we already | 425 | * sent to syslog/printk. remember loss here is ok. we already |
426 | * called audit_log_lost() if it didn't go out normally. so the | 426 | * called audit_log_lost() if it didn't go out normally. so the |
427 | * race between the skb_dequeue and the next check for audit_pid | 427 | * race between the skb_dequeue and the next check for audit_pid |
428 | * doesn't matter. | 428 | * doesn't matter. |
429 | * | 429 | * |
430 | * if you ever find kauditd to be too slow we can get a perf win | 430 | * if you ever find kauditd to be too slow we can get a perf win |
431 | * by doing our own locking and keeping better track if there | 431 | * by doing our own locking and keeping better track if there |
432 | * are messages in this queue. I don't see the need now, but | 432 | * are messages in this queue. I don't see the need now, but |
433 | * in 5 years when I want to play with this again I'll see this | 433 | * in 5 years when I want to play with this again I'll see this |
434 | * note and still have no friggin idea what i'm thinking today. | 434 | * note and still have no friggin idea what i'm thinking today. |
435 | */ | 435 | */ |
436 | if (audit_default && audit_pid) { | 436 | if (audit_default && audit_pid) { |
437 | skb = skb_dequeue(&audit_skb_hold_queue); | 437 | skb = skb_dequeue(&audit_skb_hold_queue); |
438 | if (unlikely(skb)) { | 438 | if (unlikely(skb)) { |
439 | while (skb && audit_pid) { | 439 | while (skb && audit_pid) { |
440 | kauditd_send_skb(skb); | 440 | kauditd_send_skb(skb); |
441 | skb = skb_dequeue(&audit_skb_hold_queue); | 441 | skb = skb_dequeue(&audit_skb_hold_queue); |
442 | } | 442 | } |
443 | } | 443 | } |
444 | } | 444 | } |
445 | 445 | ||
446 | skb = skb_dequeue(&audit_skb_queue); | 446 | skb = skb_dequeue(&audit_skb_queue); |
447 | wake_up(&audit_backlog_wait); | 447 | wake_up(&audit_backlog_wait); |
448 | if (skb) { | 448 | if (skb) { |
449 | if (audit_pid) | 449 | if (audit_pid) |
450 | kauditd_send_skb(skb); | 450 | kauditd_send_skb(skb); |
451 | else | 451 | else |
452 | audit_printk_skb(skb); | 452 | audit_printk_skb(skb); |
453 | } else { | 453 | } else { |
454 | DECLARE_WAITQUEUE(wait, current); | 454 | DECLARE_WAITQUEUE(wait, current); |
455 | set_current_state(TASK_INTERRUPTIBLE); | 455 | set_current_state(TASK_INTERRUPTIBLE); |
456 | add_wait_queue(&kauditd_wait, &wait); | 456 | add_wait_queue(&kauditd_wait, &wait); |
457 | 457 | ||
458 | if (!skb_queue_len(&audit_skb_queue)) { | 458 | if (!skb_queue_len(&audit_skb_queue)) { |
459 | try_to_freeze(); | 459 | try_to_freeze(); |
460 | schedule(); | 460 | schedule(); |
461 | } | 461 | } |
462 | 462 | ||
463 | __set_current_state(TASK_RUNNING); | 463 | __set_current_state(TASK_RUNNING); |
464 | remove_wait_queue(&kauditd_wait, &wait); | 464 | remove_wait_queue(&kauditd_wait, &wait); |
465 | } | 465 | } |
466 | } | 466 | } |
467 | return 0; | 467 | return 0; |
468 | } | 468 | } |
469 | 469 | ||
470 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) | 470 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) |
471 | { | 471 | { |
472 | struct task_struct *tsk; | 472 | struct task_struct *tsk; |
473 | int err; | 473 | int err; |
474 | 474 | ||
475 | rcu_read_lock(); | 475 | rcu_read_lock(); |
476 | tsk = find_task_by_vpid(pid); | 476 | tsk = find_task_by_vpid(pid); |
477 | if (!tsk) { | 477 | if (!tsk) { |
478 | rcu_read_unlock(); | 478 | rcu_read_unlock(); |
479 | return -ESRCH; | 479 | return -ESRCH; |
480 | } | 480 | } |
481 | get_task_struct(tsk); | 481 | get_task_struct(tsk); |
482 | rcu_read_unlock(); | 482 | rcu_read_unlock(); |
483 | err = tty_audit_push_task(tsk, loginuid, sessionid); | 483 | err = tty_audit_push_task(tsk, loginuid, sessionid); |
484 | put_task_struct(tsk); | 484 | put_task_struct(tsk); |
485 | return err; | 485 | return err; |
486 | } | 486 | } |
487 | 487 | ||
488 | int audit_send_list(void *_dest) | 488 | int audit_send_list(void *_dest) |
489 | { | 489 | { |
490 | struct audit_netlink_list *dest = _dest; | 490 | struct audit_netlink_list *dest = _dest; |
491 | int pid = dest->pid; | 491 | int pid = dest->pid; |
492 | struct sk_buff *skb; | 492 | struct sk_buff *skb; |
493 | 493 | ||
494 | /* wait for parent to finish and send an ACK */ | 494 | /* wait for parent to finish and send an ACK */ |
495 | mutex_lock(&audit_cmd_mutex); | 495 | mutex_lock(&audit_cmd_mutex); |
496 | mutex_unlock(&audit_cmd_mutex); | 496 | mutex_unlock(&audit_cmd_mutex); |
497 | 497 | ||
498 | while ((skb = __skb_dequeue(&dest->q)) != NULL) | 498 | while ((skb = __skb_dequeue(&dest->q)) != NULL) |
499 | netlink_unicast(audit_sock, skb, pid, 0); | 499 | netlink_unicast(audit_sock, skb, pid, 0); |
500 | 500 | ||
501 | kfree(dest); | 501 | kfree(dest); |
502 | 502 | ||
503 | return 0; | 503 | return 0; |
504 | } | 504 | } |
505 | 505 | ||
506 | struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, | 506 | struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, |
507 | int multi, const void *payload, int size) | 507 | int multi, const void *payload, int size) |
508 | { | 508 | { |
509 | struct sk_buff *skb; | 509 | struct sk_buff *skb; |
510 | struct nlmsghdr *nlh; | 510 | struct nlmsghdr *nlh; |
511 | void *data; | 511 | void *data; |
512 | int flags = multi ? NLM_F_MULTI : 0; | 512 | int flags = multi ? NLM_F_MULTI : 0; |
513 | int t = done ? NLMSG_DONE : type; | 513 | int t = done ? NLMSG_DONE : type; |
514 | 514 | ||
515 | skb = nlmsg_new(size, GFP_KERNEL); | 515 | skb = nlmsg_new(size, GFP_KERNEL); |
516 | if (!skb) | 516 | if (!skb) |
517 | return NULL; | 517 | return NULL; |
518 | 518 | ||
519 | nlh = NLMSG_NEW(skb, pid, seq, t, size, flags); | 519 | nlh = NLMSG_NEW(skb, pid, seq, t, size, flags); |
520 | data = NLMSG_DATA(nlh); | 520 | data = NLMSG_DATA(nlh); |
521 | memcpy(data, payload, size); | 521 | memcpy(data, payload, size); |
522 | return skb; | 522 | return skb; |
523 | 523 | ||
524 | nlmsg_failure: /* Used by NLMSG_NEW */ | 524 | nlmsg_failure: /* Used by NLMSG_NEW */ |
525 | if (skb) | 525 | if (skb) |
526 | kfree_skb(skb); | 526 | kfree_skb(skb); |
527 | return NULL; | 527 | return NULL; |
528 | } | 528 | } |
529 | 529 | ||
530 | static int audit_send_reply_thread(void *arg) | 530 | static int audit_send_reply_thread(void *arg) |
531 | { | 531 | { |
532 | struct audit_reply *reply = (struct audit_reply *)arg; | 532 | struct audit_reply *reply = (struct audit_reply *)arg; |
533 | 533 | ||
534 | mutex_lock(&audit_cmd_mutex); | 534 | mutex_lock(&audit_cmd_mutex); |
535 | mutex_unlock(&audit_cmd_mutex); | 535 | mutex_unlock(&audit_cmd_mutex); |
536 | 536 | ||
537 | /* Ignore failure. It'll only happen if the sender goes away, | 537 | /* Ignore failure. It'll only happen if the sender goes away, |
538 | because our timeout is set to infinite. */ | 538 | because our timeout is set to infinite. */ |
539 | netlink_unicast(audit_sock, reply->skb, reply->pid, 0); | 539 | netlink_unicast(audit_sock, reply->skb, reply->pid, 0); |
540 | kfree(reply); | 540 | kfree(reply); |
541 | return 0; | 541 | return 0; |
542 | } | 542 | } |
543 | /** | 543 | /** |
544 | * audit_send_reply - send an audit reply message via netlink | 544 | * audit_send_reply - send an audit reply message via netlink |
545 | * @pid: process id to send reply to | 545 | * @pid: process id to send reply to |
546 | * @seq: sequence number | 546 | * @seq: sequence number |
547 | * @type: audit message type | 547 | * @type: audit message type |
548 | * @done: done (last) flag | 548 | * @done: done (last) flag |
549 | * @multi: multi-part message flag | 549 | * @multi: multi-part message flag |
550 | * @payload: payload data | 550 | * @payload: payload data |
551 | * @size: payload size | 551 | * @size: payload size |
552 | * | 552 | * |
553 | * Allocates an skb, builds the netlink message, and sends it to the pid. | 553 | * Allocates an skb, builds the netlink message, and sends it to the pid. |
554 | * No failure notifications. | 554 | * No failure notifications. |
555 | */ | 555 | */ |
556 | static void audit_send_reply(int pid, int seq, int type, int done, int multi, | 556 | static void audit_send_reply(int pid, int seq, int type, int done, int multi, |
557 | const void *payload, int size) | 557 | const void *payload, int size) |
558 | { | 558 | { |
559 | struct sk_buff *skb; | 559 | struct sk_buff *skb; |
560 | struct task_struct *tsk; | 560 | struct task_struct *tsk; |
561 | struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), | 561 | struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), |
562 | GFP_KERNEL); | 562 | GFP_KERNEL); |
563 | 563 | ||
564 | if (!reply) | 564 | if (!reply) |
565 | return; | 565 | return; |
566 | 566 | ||
567 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); | 567 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); |
568 | if (!skb) | 568 | if (!skb) |
569 | goto out; | 569 | goto out; |
570 | 570 | ||
571 | reply->pid = pid; | 571 | reply->pid = pid; |
572 | reply->skb = skb; | 572 | reply->skb = skb; |
573 | 573 | ||
574 | tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); | 574 | tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); |
575 | if (!IS_ERR(tsk)) | 575 | if (!IS_ERR(tsk)) |
576 | return; | 576 | return; |
577 | kfree_skb(skb); | 577 | kfree_skb(skb); |
578 | out: | 578 | out: |
579 | kfree(reply); | 579 | kfree(reply); |
580 | } | 580 | } |
581 | 581 | ||
582 | /* | 582 | /* |
583 | * Check for appropriate CAP_AUDIT_ capabilities on incoming audit | 583 | * Check for appropriate CAP_AUDIT_ capabilities on incoming audit |
584 | * control messages. | 584 | * control messages. |
585 | */ | 585 | */ |
586 | static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | 586 | static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) |
587 | { | 587 | { |
588 | int err = 0; | 588 | int err = 0; |
589 | 589 | ||
590 | switch (msg_type) { | 590 | switch (msg_type) { |
591 | case AUDIT_GET: | 591 | case AUDIT_GET: |
592 | case AUDIT_LIST: | 592 | case AUDIT_LIST: |
593 | case AUDIT_LIST_RULES: | 593 | case AUDIT_LIST_RULES: |
594 | case AUDIT_SET: | 594 | case AUDIT_SET: |
595 | case AUDIT_ADD: | 595 | case AUDIT_ADD: |
596 | case AUDIT_ADD_RULE: | 596 | case AUDIT_ADD_RULE: |
597 | case AUDIT_DEL: | 597 | case AUDIT_DEL: |
598 | case AUDIT_DEL_RULE: | 598 | case AUDIT_DEL_RULE: |
599 | case AUDIT_SIGNAL_INFO: | 599 | case AUDIT_SIGNAL_INFO: |
600 | case AUDIT_TTY_GET: | 600 | case AUDIT_TTY_GET: |
601 | case AUDIT_TTY_SET: | 601 | case AUDIT_TTY_SET: |
602 | case AUDIT_TRIM: | 602 | case AUDIT_TRIM: |
603 | case AUDIT_MAKE_EQUIV: | 603 | case AUDIT_MAKE_EQUIV: |
604 | if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) | 604 | if (!capable(CAP_AUDIT_CONTROL)) |
605 | err = -EPERM; | 605 | err = -EPERM; |
606 | break; | 606 | break; |
607 | case AUDIT_USER: | 607 | case AUDIT_USER: |
608 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 608 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
609 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: | 609 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: |
610 | if (security_netlink_recv(skb, CAP_AUDIT_WRITE)) | 610 | if (!capable(CAP_AUDIT_WRITE)) |
611 | err = -EPERM; | 611 | err = -EPERM; |
612 | break; | 612 | break; |
613 | default: /* bad msg */ | 613 | default: /* bad msg */ |
614 | err = -EINVAL; | 614 | err = -EINVAL; |
615 | } | 615 | } |
616 | 616 | ||
617 | return err; | 617 | return err; |
618 | } | 618 | } |
619 | 619 | ||
620 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | 620 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, |
621 | u32 pid, u32 uid, uid_t auid, u32 ses, | 621 | u32 pid, u32 uid, uid_t auid, u32 ses, |
622 | u32 sid) | 622 | u32 sid) |
623 | { | 623 | { |
624 | int rc = 0; | 624 | int rc = 0; |
625 | char *ctx = NULL; | 625 | char *ctx = NULL; |
626 | u32 len; | 626 | u32 len; |
627 | 627 | ||
628 | if (!audit_enabled) { | 628 | if (!audit_enabled) { |
629 | *ab = NULL; | 629 | *ab = NULL; |
630 | return rc; | 630 | return rc; |
631 | } | 631 | } |
632 | 632 | ||
633 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 633 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
634 | audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u", | 634 | audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u", |
635 | pid, uid, auid, ses); | 635 | pid, uid, auid, ses); |
636 | if (sid) { | 636 | if (sid) { |
637 | rc = security_secid_to_secctx(sid, &ctx, &len); | 637 | rc = security_secid_to_secctx(sid, &ctx, &len); |
638 | if (rc) | 638 | if (rc) |
639 | audit_log_format(*ab, " ssid=%u", sid); | 639 | audit_log_format(*ab, " ssid=%u", sid); |
640 | else { | 640 | else { |
641 | audit_log_format(*ab, " subj=%s", ctx); | 641 | audit_log_format(*ab, " subj=%s", ctx); |
642 | security_release_secctx(ctx, len); | 642 | security_release_secctx(ctx, len); |
643 | } | 643 | } |
644 | } | 644 | } |
645 | 645 | ||
646 | return rc; | 646 | return rc; |
647 | } | 647 | } |
648 | 648 | ||
649 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 649 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
650 | { | 650 | { |
651 | u32 uid, pid, seq, sid; | 651 | u32 uid, pid, seq, sid; |
652 | void *data; | 652 | void *data; |
653 | struct audit_status *status_get, status_set; | 653 | struct audit_status *status_get, status_set; |
654 | int err; | 654 | int err; |
655 | struct audit_buffer *ab; | 655 | struct audit_buffer *ab; |
656 | u16 msg_type = nlh->nlmsg_type; | 656 | u16 msg_type = nlh->nlmsg_type; |
657 | uid_t loginuid; /* loginuid of sender */ | 657 | uid_t loginuid; /* loginuid of sender */ |
658 | u32 sessionid; | 658 | u32 sessionid; |
659 | struct audit_sig_info *sig_data; | 659 | struct audit_sig_info *sig_data; |
660 | char *ctx = NULL; | 660 | char *ctx = NULL; |
661 | u32 len; | 661 | u32 len; |
662 | 662 | ||
663 | err = audit_netlink_ok(skb, msg_type); | 663 | err = audit_netlink_ok(skb, msg_type); |
664 | if (err) | 664 | if (err) |
665 | return err; | 665 | return err; |
666 | 666 | ||
667 | /* As soon as there's any sign of userspace auditd, | 667 | /* As soon as there's any sign of userspace auditd, |
668 | * start kauditd to talk to it */ | 668 | * start kauditd to talk to it */ |
669 | if (!kauditd_task) | 669 | if (!kauditd_task) |
670 | kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); | 670 | kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); |
671 | if (IS_ERR(kauditd_task)) { | 671 | if (IS_ERR(kauditd_task)) { |
672 | err = PTR_ERR(kauditd_task); | 672 | err = PTR_ERR(kauditd_task); |
673 | kauditd_task = NULL; | 673 | kauditd_task = NULL; |
674 | return err; | 674 | return err; |
675 | } | 675 | } |
676 | 676 | ||
677 | pid = NETLINK_CREDS(skb)->pid; | 677 | pid = NETLINK_CREDS(skb)->pid; |
678 | uid = NETLINK_CREDS(skb)->uid; | 678 | uid = NETLINK_CREDS(skb)->uid; |
679 | loginuid = audit_get_loginuid(current); | 679 | loginuid = audit_get_loginuid(current); |
680 | sessionid = audit_get_sessionid(current); | 680 | sessionid = audit_get_sessionid(current); |
681 | security_task_getsecid(current, &sid); | 681 | security_task_getsecid(current, &sid); |
682 | seq = nlh->nlmsg_seq; | 682 | seq = nlh->nlmsg_seq; |
683 | data = NLMSG_DATA(nlh); | 683 | data = NLMSG_DATA(nlh); |
684 | 684 | ||
685 | switch (msg_type) { | 685 | switch (msg_type) { |
686 | case AUDIT_GET: | 686 | case AUDIT_GET: |
687 | status_set.enabled = audit_enabled; | 687 | status_set.enabled = audit_enabled; |
688 | status_set.failure = audit_failure; | 688 | status_set.failure = audit_failure; |
689 | status_set.pid = audit_pid; | 689 | status_set.pid = audit_pid; |
690 | status_set.rate_limit = audit_rate_limit; | 690 | status_set.rate_limit = audit_rate_limit; |
691 | status_set.backlog_limit = audit_backlog_limit; | 691 | status_set.backlog_limit = audit_backlog_limit; |
692 | status_set.lost = atomic_read(&audit_lost); | 692 | status_set.lost = atomic_read(&audit_lost); |
693 | status_set.backlog = skb_queue_len(&audit_skb_queue); | 693 | status_set.backlog = skb_queue_len(&audit_skb_queue); |
694 | audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, | 694 | audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, |
695 | &status_set, sizeof(status_set)); | 695 | &status_set, sizeof(status_set)); |
696 | break; | 696 | break; |
697 | case AUDIT_SET: | 697 | case AUDIT_SET: |
698 | if (nlh->nlmsg_len < sizeof(struct audit_status)) | 698 | if (nlh->nlmsg_len < sizeof(struct audit_status)) |
699 | return -EINVAL; | 699 | return -EINVAL; |
700 | status_get = (struct audit_status *)data; | 700 | status_get = (struct audit_status *)data; |
701 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 701 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
702 | err = audit_set_enabled(status_get->enabled, | 702 | err = audit_set_enabled(status_get->enabled, |
703 | loginuid, sessionid, sid); | 703 | loginuid, sessionid, sid); |
704 | if (err < 0) | 704 | if (err < 0) |
705 | return err; | 705 | return err; |
706 | } | 706 | } |
707 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 707 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
708 | err = audit_set_failure(status_get->failure, | 708 | err = audit_set_failure(status_get->failure, |
709 | loginuid, sessionid, sid); | 709 | loginuid, sessionid, sid); |
710 | if (err < 0) | 710 | if (err < 0) |
711 | return err; | 711 | return err; |
712 | } | 712 | } |
713 | if (status_get->mask & AUDIT_STATUS_PID) { | 713 | if (status_get->mask & AUDIT_STATUS_PID) { |
714 | int new_pid = status_get->pid; | 714 | int new_pid = status_get->pid; |
715 | 715 | ||
716 | if (audit_enabled != AUDIT_OFF) | 716 | if (audit_enabled != AUDIT_OFF) |
717 | audit_log_config_change("audit_pid", new_pid, | 717 | audit_log_config_change("audit_pid", new_pid, |
718 | audit_pid, loginuid, | 718 | audit_pid, loginuid, |
719 | sessionid, sid, 1); | 719 | sessionid, sid, 1); |
720 | 720 | ||
721 | audit_pid = new_pid; | 721 | audit_pid = new_pid; |
722 | audit_nlk_pid = NETLINK_CB(skb).pid; | 722 | audit_nlk_pid = NETLINK_CB(skb).pid; |
723 | } | 723 | } |
724 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { | 724 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { |
725 | err = audit_set_rate_limit(status_get->rate_limit, | 725 | err = audit_set_rate_limit(status_get->rate_limit, |
726 | loginuid, sessionid, sid); | 726 | loginuid, sessionid, sid); |
727 | if (err < 0) | 727 | if (err < 0) |
728 | return err; | 728 | return err; |
729 | } | 729 | } |
730 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 730 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
731 | err = audit_set_backlog_limit(status_get->backlog_limit, | 731 | err = audit_set_backlog_limit(status_get->backlog_limit, |
732 | loginuid, sessionid, sid); | 732 | loginuid, sessionid, sid); |
733 | break; | 733 | break; |
734 | case AUDIT_USER: | 734 | case AUDIT_USER: |
735 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 735 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
736 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: | 736 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: |
737 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 737 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
738 | return 0; | 738 | return 0; |
739 | 739 | ||
740 | err = audit_filter_user(&NETLINK_CB(skb)); | 740 | err = audit_filter_user(&NETLINK_CB(skb)); |
741 | if (err == 1) { | 741 | if (err == 1) { |
742 | err = 0; | 742 | err = 0; |
743 | if (msg_type == AUDIT_USER_TTY) { | 743 | if (msg_type == AUDIT_USER_TTY) { |
744 | err = audit_prepare_user_tty(pid, loginuid, | 744 | err = audit_prepare_user_tty(pid, loginuid, |
745 | sessionid); | 745 | sessionid); |
746 | if (err) | 746 | if (err) |
747 | break; | 747 | break; |
748 | } | 748 | } |
749 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, | 749 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, |
750 | loginuid, sessionid, sid); | 750 | loginuid, sessionid, sid); |
751 | 751 | ||
752 | if (msg_type != AUDIT_USER_TTY) | 752 | if (msg_type != AUDIT_USER_TTY) |
753 | audit_log_format(ab, " msg='%.1024s'", | 753 | audit_log_format(ab, " msg='%.1024s'", |
754 | (char *)data); | 754 | (char *)data); |
755 | else { | 755 | else { |
756 | int size; | 756 | int size; |
757 | 757 | ||
758 | audit_log_format(ab, " msg="); | 758 | audit_log_format(ab, " msg="); |
759 | size = nlmsg_len(nlh); | 759 | size = nlmsg_len(nlh); |
760 | if (size > 0 && | 760 | if (size > 0 && |
761 | ((unsigned char *)data)[size - 1] == '\0') | 761 | ((unsigned char *)data)[size - 1] == '\0') |
762 | size--; | 762 | size--; |
763 | audit_log_n_untrustedstring(ab, data, size); | 763 | audit_log_n_untrustedstring(ab, data, size); |
764 | } | 764 | } |
765 | audit_set_pid(ab, pid); | 765 | audit_set_pid(ab, pid); |
766 | audit_log_end(ab); | 766 | audit_log_end(ab); |
767 | } | 767 | } |
768 | break; | 768 | break; |
769 | case AUDIT_ADD: | 769 | case AUDIT_ADD: |
770 | case AUDIT_DEL: | 770 | case AUDIT_DEL: |
771 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | 771 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) |
772 | return -EINVAL; | 772 | return -EINVAL; |
773 | if (audit_enabled == AUDIT_LOCKED) { | 773 | if (audit_enabled == AUDIT_LOCKED) { |
774 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 774 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
775 | uid, loginuid, sessionid, sid); | 775 | uid, loginuid, sessionid, sid); |
776 | 776 | ||
777 | audit_log_format(ab, " audit_enabled=%d res=0", | 777 | audit_log_format(ab, " audit_enabled=%d res=0", |
778 | audit_enabled); | 778 | audit_enabled); |
779 | audit_log_end(ab); | 779 | audit_log_end(ab); |
780 | return -EPERM; | 780 | return -EPERM; |
781 | } | 781 | } |
782 | /* fallthrough */ | 782 | /* fallthrough */ |
783 | case AUDIT_LIST: | 783 | case AUDIT_LIST: |
784 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, | 784 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, |
785 | uid, seq, data, nlmsg_len(nlh), | 785 | uid, seq, data, nlmsg_len(nlh), |
786 | loginuid, sessionid, sid); | 786 | loginuid, sessionid, sid); |
787 | break; | 787 | break; |
788 | case AUDIT_ADD_RULE: | 788 | case AUDIT_ADD_RULE: |
789 | case AUDIT_DEL_RULE: | 789 | case AUDIT_DEL_RULE: |
790 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 790 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
791 | return -EINVAL; | 791 | return -EINVAL; |
792 | if (audit_enabled == AUDIT_LOCKED) { | 792 | if (audit_enabled == AUDIT_LOCKED) { |
793 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 793 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
794 | uid, loginuid, sessionid, sid); | 794 | uid, loginuid, sessionid, sid); |
795 | 795 | ||
796 | audit_log_format(ab, " audit_enabled=%d res=0", | 796 | audit_log_format(ab, " audit_enabled=%d res=0", |
797 | audit_enabled); | 797 | audit_enabled); |
798 | audit_log_end(ab); | 798 | audit_log_end(ab); |
799 | return -EPERM; | 799 | return -EPERM; |
800 | } | 800 | } |
801 | /* fallthrough */ | 801 | /* fallthrough */ |
802 | case AUDIT_LIST_RULES: | 802 | case AUDIT_LIST_RULES: |
803 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, | 803 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, |
804 | uid, seq, data, nlmsg_len(nlh), | 804 | uid, seq, data, nlmsg_len(nlh), |
805 | loginuid, sessionid, sid); | 805 | loginuid, sessionid, sid); |
806 | break; | 806 | break; |
807 | case AUDIT_TRIM: | 807 | case AUDIT_TRIM: |
808 | audit_trim_trees(); | 808 | audit_trim_trees(); |
809 | 809 | ||
810 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 810 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
811 | uid, loginuid, sessionid, sid); | 811 | uid, loginuid, sessionid, sid); |
812 | 812 | ||
813 | audit_log_format(ab, " op=trim res=1"); | 813 | audit_log_format(ab, " op=trim res=1"); |
814 | audit_log_end(ab); | 814 | audit_log_end(ab); |
815 | break; | 815 | break; |
816 | case AUDIT_MAKE_EQUIV: { | 816 | case AUDIT_MAKE_EQUIV: { |
817 | void *bufp = data; | 817 | void *bufp = data; |
818 | u32 sizes[2]; | 818 | u32 sizes[2]; |
819 | size_t msglen = nlmsg_len(nlh); | 819 | size_t msglen = nlmsg_len(nlh); |
820 | char *old, *new; | 820 | char *old, *new; |
821 | 821 | ||
822 | err = -EINVAL; | 822 | err = -EINVAL; |
823 | if (msglen < 2 * sizeof(u32)) | 823 | if (msglen < 2 * sizeof(u32)) |
824 | break; | 824 | break; |
825 | memcpy(sizes, bufp, 2 * sizeof(u32)); | 825 | memcpy(sizes, bufp, 2 * sizeof(u32)); |
826 | bufp += 2 * sizeof(u32); | 826 | bufp += 2 * sizeof(u32); |
827 | msglen -= 2 * sizeof(u32); | 827 | msglen -= 2 * sizeof(u32); |
828 | old = audit_unpack_string(&bufp, &msglen, sizes[0]); | 828 | old = audit_unpack_string(&bufp, &msglen, sizes[0]); |
829 | if (IS_ERR(old)) { | 829 | if (IS_ERR(old)) { |
830 | err = PTR_ERR(old); | 830 | err = PTR_ERR(old); |
831 | break; | 831 | break; |
832 | } | 832 | } |
833 | new = audit_unpack_string(&bufp, &msglen, sizes[1]); | 833 | new = audit_unpack_string(&bufp, &msglen, sizes[1]); |
834 | if (IS_ERR(new)) { | 834 | if (IS_ERR(new)) { |
835 | err = PTR_ERR(new); | 835 | err = PTR_ERR(new); |
836 | kfree(old); | 836 | kfree(old); |
837 | break; | 837 | break; |
838 | } | 838 | } |
839 | /* OK, here comes... */ | 839 | /* OK, here comes... */ |
840 | err = audit_tag_tree(old, new); | 840 | err = audit_tag_tree(old, new); |
841 | 841 | ||
842 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 842 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
843 | uid, loginuid, sessionid, sid); | 843 | uid, loginuid, sessionid, sid); |
844 | 844 | ||
845 | audit_log_format(ab, " op=make_equiv old="); | 845 | audit_log_format(ab, " op=make_equiv old="); |
846 | audit_log_untrustedstring(ab, old); | 846 | audit_log_untrustedstring(ab, old); |
847 | audit_log_format(ab, " new="); | 847 | audit_log_format(ab, " new="); |
848 | audit_log_untrustedstring(ab, new); | 848 | audit_log_untrustedstring(ab, new); |
849 | audit_log_format(ab, " res=%d", !err); | 849 | audit_log_format(ab, " res=%d", !err); |
850 | audit_log_end(ab); | 850 | audit_log_end(ab); |
851 | kfree(old); | 851 | kfree(old); |
852 | kfree(new); | 852 | kfree(new); |
853 | break; | 853 | break; |
854 | } | 854 | } |
855 | case AUDIT_SIGNAL_INFO: | 855 | case AUDIT_SIGNAL_INFO: |
856 | len = 0; | 856 | len = 0; |
857 | if (audit_sig_sid) { | 857 | if (audit_sig_sid) { |
858 | err = security_secid_to_secctx(audit_sig_sid, &ctx, &len); | 858 | err = security_secid_to_secctx(audit_sig_sid, &ctx, &len); |
859 | if (err) | 859 | if (err) |
860 | return err; | 860 | return err; |
861 | } | 861 | } |
862 | sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL); | 862 | sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL); |
863 | if (!sig_data) { | 863 | if (!sig_data) { |
864 | if (audit_sig_sid) | 864 | if (audit_sig_sid) |
865 | security_release_secctx(ctx, len); | 865 | security_release_secctx(ctx, len); |
866 | return -ENOMEM; | 866 | return -ENOMEM; |
867 | } | 867 | } |
868 | sig_data->uid = audit_sig_uid; | 868 | sig_data->uid = audit_sig_uid; |
869 | sig_data->pid = audit_sig_pid; | 869 | sig_data->pid = audit_sig_pid; |
870 | if (audit_sig_sid) { | 870 | if (audit_sig_sid) { |
871 | memcpy(sig_data->ctx, ctx, len); | 871 | memcpy(sig_data->ctx, ctx, len); |
872 | security_release_secctx(ctx, len); | 872 | security_release_secctx(ctx, len); |
873 | } | 873 | } |
874 | audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, | 874 | audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, |
875 | 0, 0, sig_data, sizeof(*sig_data) + len); | 875 | 0, 0, sig_data, sizeof(*sig_data) + len); |
876 | kfree(sig_data); | 876 | kfree(sig_data); |
877 | break; | 877 | break; |
878 | case AUDIT_TTY_GET: { | 878 | case AUDIT_TTY_GET: { |
879 | struct audit_tty_status s; | 879 | struct audit_tty_status s; |
880 | struct task_struct *tsk; | 880 | struct task_struct *tsk; |
881 | unsigned long flags; | 881 | unsigned long flags; |
882 | 882 | ||
883 | rcu_read_lock(); | 883 | rcu_read_lock(); |
884 | tsk = find_task_by_vpid(pid); | 884 | tsk = find_task_by_vpid(pid); |
885 | if (tsk && lock_task_sighand(tsk, &flags)) { | 885 | if (tsk && lock_task_sighand(tsk, &flags)) { |
886 | s.enabled = tsk->signal->audit_tty != 0; | 886 | s.enabled = tsk->signal->audit_tty != 0; |
887 | unlock_task_sighand(tsk, &flags); | 887 | unlock_task_sighand(tsk, &flags); |
888 | } else | 888 | } else |
889 | err = -ESRCH; | 889 | err = -ESRCH; |
890 | rcu_read_unlock(); | 890 | rcu_read_unlock(); |
891 | 891 | ||
892 | if (!err) | 892 | if (!err) |
893 | audit_send_reply(NETLINK_CB(skb).pid, seq, | 893 | audit_send_reply(NETLINK_CB(skb).pid, seq, |
894 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); | 894 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); |
895 | break; | 895 | break; |
896 | } | 896 | } |
897 | case AUDIT_TTY_SET: { | 897 | case AUDIT_TTY_SET: { |
898 | struct audit_tty_status *s; | 898 | struct audit_tty_status *s; |
899 | struct task_struct *tsk; | 899 | struct task_struct *tsk; |
900 | unsigned long flags; | 900 | unsigned long flags; |
901 | 901 | ||
902 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | 902 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) |
903 | return -EINVAL; | 903 | return -EINVAL; |
904 | s = data; | 904 | s = data; |
905 | if (s->enabled != 0 && s->enabled != 1) | 905 | if (s->enabled != 0 && s->enabled != 1) |
906 | return -EINVAL; | 906 | return -EINVAL; |
907 | rcu_read_lock(); | 907 | rcu_read_lock(); |
908 | tsk = find_task_by_vpid(pid); | 908 | tsk = find_task_by_vpid(pid); |
909 | if (tsk && lock_task_sighand(tsk, &flags)) { | 909 | if (tsk && lock_task_sighand(tsk, &flags)) { |
910 | tsk->signal->audit_tty = s->enabled != 0; | 910 | tsk->signal->audit_tty = s->enabled != 0; |
911 | unlock_task_sighand(tsk, &flags); | 911 | unlock_task_sighand(tsk, &flags); |
912 | } else | 912 | } else |
913 | err = -ESRCH; | 913 | err = -ESRCH; |
914 | rcu_read_unlock(); | 914 | rcu_read_unlock(); |
915 | break; | 915 | break; |
916 | } | 916 | } |
917 | default: | 917 | default: |
918 | err = -EINVAL; | 918 | err = -EINVAL; |
919 | break; | 919 | break; |
920 | } | 920 | } |
921 | 921 | ||
922 | return err < 0 ? err : 0; | 922 | return err < 0 ? err : 0; |
923 | } | 923 | } |
924 | 924 | ||
925 | /* | 925 | /* |
926 | * Get message from skb. Each message is processed by audit_receive_msg. | 926 | * Get message from skb. Each message is processed by audit_receive_msg. |
927 | * Malformed skbs with wrong length are discarded silently. | 927 | * Malformed skbs with wrong length are discarded silently. |
928 | */ | 928 | */ |
929 | static void audit_receive_skb(struct sk_buff *skb) | 929 | static void audit_receive_skb(struct sk_buff *skb) |
930 | { | 930 | { |
931 | struct nlmsghdr *nlh; | 931 | struct nlmsghdr *nlh; |
932 | /* | 932 | /* |
933 | * len MUST be signed for NLMSG_NEXT to be able to dec it below 0 | 933 | * len MUST be signed for NLMSG_NEXT to be able to dec it below 0 |
934 | * if the nlmsg_len was not aligned | 934 | * if the nlmsg_len was not aligned |
935 | */ | 935 | */ |
936 | int len; | 936 | int len; |
937 | int err; | 937 | int err; |
938 | 938 | ||
939 | nlh = nlmsg_hdr(skb); | 939 | nlh = nlmsg_hdr(skb); |
940 | len = skb->len; | 940 | len = skb->len; |
941 | 941 | ||
942 | while (NLMSG_OK(nlh, len)) { | 942 | while (NLMSG_OK(nlh, len)) { |
943 | err = audit_receive_msg(skb, nlh); | 943 | err = audit_receive_msg(skb, nlh); |
944 | /* if err or if this message says it wants a response */ | 944 | /* if err or if this message says it wants a response */ |
945 | if (err || (nlh->nlmsg_flags & NLM_F_ACK)) | 945 | if (err || (nlh->nlmsg_flags & NLM_F_ACK)) |
946 | netlink_ack(skb, nlh, err); | 946 | netlink_ack(skb, nlh, err); |
947 | 947 | ||
948 | nlh = NLMSG_NEXT(nlh, len); | 948 | nlh = NLMSG_NEXT(nlh, len); |
949 | } | 949 | } |
950 | } | 950 | } |
951 | 951 | ||
952 | /* Receive messages from netlink socket. */ | 952 | /* Receive messages from netlink socket. */ |
953 | static void audit_receive(struct sk_buff *skb) | 953 | static void audit_receive(struct sk_buff *skb) |
954 | { | 954 | { |
955 | mutex_lock(&audit_cmd_mutex); | 955 | mutex_lock(&audit_cmd_mutex); |
956 | audit_receive_skb(skb); | 956 | audit_receive_skb(skb); |
957 | mutex_unlock(&audit_cmd_mutex); | 957 | mutex_unlock(&audit_cmd_mutex); |
958 | } | 958 | } |
959 | 959 | ||
960 | /* Initialize audit support at boot time. */ | 960 | /* Initialize audit support at boot time. */ |
961 | static int __init audit_init(void) | 961 | static int __init audit_init(void) |
962 | { | 962 | { |
963 | int i; | 963 | int i; |
964 | 964 | ||
965 | if (audit_initialized == AUDIT_DISABLED) | 965 | if (audit_initialized == AUDIT_DISABLED) |
966 | return 0; | 966 | return 0; |
967 | 967 | ||
968 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", | 968 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", |
969 | audit_default ? "enabled" : "disabled"); | 969 | audit_default ? "enabled" : "disabled"); |
970 | audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0, | 970 | audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0, |
971 | audit_receive, NULL, THIS_MODULE); | 971 | audit_receive, NULL, THIS_MODULE); |
972 | if (!audit_sock) | 972 | if (!audit_sock) |
973 | audit_panic("cannot initialize netlink socket"); | 973 | audit_panic("cannot initialize netlink socket"); |
974 | else | 974 | else |
975 | audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | 975 | audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; |
976 | 976 | ||
977 | skb_queue_head_init(&audit_skb_queue); | 977 | skb_queue_head_init(&audit_skb_queue); |
978 | skb_queue_head_init(&audit_skb_hold_queue); | 978 | skb_queue_head_init(&audit_skb_hold_queue); |
979 | audit_initialized = AUDIT_INITIALIZED; | 979 | audit_initialized = AUDIT_INITIALIZED; |
980 | audit_enabled = audit_default; | 980 | audit_enabled = audit_default; |
981 | audit_ever_enabled |= !!audit_default; | 981 | audit_ever_enabled |= !!audit_default; |
982 | 982 | ||
983 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); | 983 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); |
984 | 984 | ||
985 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) | 985 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) |
986 | INIT_LIST_HEAD(&audit_inode_hash[i]); | 986 | INIT_LIST_HEAD(&audit_inode_hash[i]); |
987 | 987 | ||
988 | return 0; | 988 | return 0; |
989 | } | 989 | } |
990 | __initcall(audit_init); | 990 | __initcall(audit_init); |
991 | 991 | ||
992 | /* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ | 992 | /* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ |
993 | static int __init audit_enable(char *str) | 993 | static int __init audit_enable(char *str) |
994 | { | 994 | { |
995 | audit_default = !!simple_strtol(str, NULL, 0); | 995 | audit_default = !!simple_strtol(str, NULL, 0); |
996 | if (!audit_default) | 996 | if (!audit_default) |
997 | audit_initialized = AUDIT_DISABLED; | 997 | audit_initialized = AUDIT_DISABLED; |
998 | 998 | ||
999 | printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled"); | 999 | printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled"); |
1000 | 1000 | ||
1001 | if (audit_initialized == AUDIT_INITIALIZED) { | 1001 | if (audit_initialized == AUDIT_INITIALIZED) { |
1002 | audit_enabled = audit_default; | 1002 | audit_enabled = audit_default; |
1003 | audit_ever_enabled |= !!audit_default; | 1003 | audit_ever_enabled |= !!audit_default; |
1004 | } else if (audit_initialized == AUDIT_UNINITIALIZED) { | 1004 | } else if (audit_initialized == AUDIT_UNINITIALIZED) { |
1005 | printk(" (after initialization)"); | 1005 | printk(" (after initialization)"); |
1006 | } else { | 1006 | } else { |
1007 | printk(" (until reboot)"); | 1007 | printk(" (until reboot)"); |
1008 | } | 1008 | } |
1009 | printk("\n"); | 1009 | printk("\n"); |
1010 | 1010 | ||
1011 | return 1; | 1011 | return 1; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | __setup("audit=", audit_enable); | 1014 | __setup("audit=", audit_enable); |
1015 | 1015 | ||
1016 | static void audit_buffer_free(struct audit_buffer *ab) | 1016 | static void audit_buffer_free(struct audit_buffer *ab) |
1017 | { | 1017 | { |
1018 | unsigned long flags; | 1018 | unsigned long flags; |
1019 | 1019 | ||
1020 | if (!ab) | 1020 | if (!ab) |
1021 | return; | 1021 | return; |
1022 | 1022 | ||
1023 | if (ab->skb) | 1023 | if (ab->skb) |
1024 | kfree_skb(ab->skb); | 1024 | kfree_skb(ab->skb); |
1025 | 1025 | ||
1026 | spin_lock_irqsave(&audit_freelist_lock, flags); | 1026 | spin_lock_irqsave(&audit_freelist_lock, flags); |
1027 | if (audit_freelist_count > AUDIT_MAXFREE) | 1027 | if (audit_freelist_count > AUDIT_MAXFREE) |
1028 | kfree(ab); | 1028 | kfree(ab); |
1029 | else { | 1029 | else { |
1030 | audit_freelist_count++; | 1030 | audit_freelist_count++; |
1031 | list_add(&ab->list, &audit_freelist); | 1031 | list_add(&ab->list, &audit_freelist); |
1032 | } | 1032 | } |
1033 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | 1033 | spin_unlock_irqrestore(&audit_freelist_lock, flags); |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | 1036 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, |
1037 | gfp_t gfp_mask, int type) | 1037 | gfp_t gfp_mask, int type) |
1038 | { | 1038 | { |
1039 | unsigned long flags; | 1039 | unsigned long flags; |
1040 | struct audit_buffer *ab = NULL; | 1040 | struct audit_buffer *ab = NULL; |
1041 | struct nlmsghdr *nlh; | 1041 | struct nlmsghdr *nlh; |
1042 | 1042 | ||
1043 | spin_lock_irqsave(&audit_freelist_lock, flags); | 1043 | spin_lock_irqsave(&audit_freelist_lock, flags); |
1044 | if (!list_empty(&audit_freelist)) { | 1044 | if (!list_empty(&audit_freelist)) { |
1045 | ab = list_entry(audit_freelist.next, | 1045 | ab = list_entry(audit_freelist.next, |
1046 | struct audit_buffer, list); | 1046 | struct audit_buffer, list); |
1047 | list_del(&ab->list); | 1047 | list_del(&ab->list); |
1048 | --audit_freelist_count; | 1048 | --audit_freelist_count; |
1049 | } | 1049 | } |
1050 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | 1050 | spin_unlock_irqrestore(&audit_freelist_lock, flags); |
1051 | 1051 | ||
1052 | if (!ab) { | 1052 | if (!ab) { |
1053 | ab = kmalloc(sizeof(*ab), gfp_mask); | 1053 | ab = kmalloc(sizeof(*ab), gfp_mask); |
1054 | if (!ab) | 1054 | if (!ab) |
1055 | goto err; | 1055 | goto err; |
1056 | } | 1056 | } |
1057 | 1057 | ||
1058 | ab->ctx = ctx; | 1058 | ab->ctx = ctx; |
1059 | ab->gfp_mask = gfp_mask; | 1059 | ab->gfp_mask = gfp_mask; |
1060 | 1060 | ||
1061 | ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask); | 1061 | ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask); |
1062 | if (!ab->skb) | 1062 | if (!ab->skb) |
1063 | goto nlmsg_failure; | 1063 | goto nlmsg_failure; |
1064 | 1064 | ||
1065 | nlh = NLMSG_NEW(ab->skb, 0, 0, type, 0, 0); | 1065 | nlh = NLMSG_NEW(ab->skb, 0, 0, type, 0, 0); |
1066 | 1066 | ||
1067 | return ab; | 1067 | return ab; |
1068 | 1068 | ||
1069 | nlmsg_failure: /* Used by NLMSG_NEW */ | 1069 | nlmsg_failure: /* Used by NLMSG_NEW */ |
1070 | kfree_skb(ab->skb); | 1070 | kfree_skb(ab->skb); |
1071 | ab->skb = NULL; | 1071 | ab->skb = NULL; |
1072 | err: | 1072 | err: |
1073 | audit_buffer_free(ab); | 1073 | audit_buffer_free(ab); |
1074 | return NULL; | 1074 | return NULL; |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | /** | 1077 | /** |
1078 | * audit_serial - compute a serial number for the audit record | 1078 | * audit_serial - compute a serial number for the audit record |
1079 | * | 1079 | * |
1080 | * Compute a serial number for the audit record. Audit records are | 1080 | * Compute a serial number for the audit record. Audit records are |
1081 | * written to user-space as soon as they are generated, so a complete | 1081 | * written to user-space as soon as they are generated, so a complete |
1082 | * audit record may be written in several pieces. The timestamp of the | 1082 | * audit record may be written in several pieces. The timestamp of the |
1083 | * record and this serial number are used by the user-space tools to | 1083 | * record and this serial number are used by the user-space tools to |
1084 | * determine which pieces belong to the same audit record. The | 1084 | * determine which pieces belong to the same audit record. The |
1085 | * (timestamp,serial) tuple is unique for each syscall and is live from | 1085 | * (timestamp,serial) tuple is unique for each syscall and is live from |
1086 | * syscall entry to syscall exit. | 1086 | * syscall entry to syscall exit. |
1087 | * | 1087 | * |
1088 | * NOTE: Another possibility is to store the formatted records off the | 1088 | * NOTE: Another possibility is to store the formatted records off the |
1089 | * audit context (for those records that have a context), and emit them | 1089 | * audit context (for those records that have a context), and emit them |
1090 | * all at syscall exit. However, this could delay the reporting of | 1090 | * all at syscall exit. However, this could delay the reporting of |
1091 | * significant errors until syscall exit (or never, if the system | 1091 | * significant errors until syscall exit (or never, if the system |
1092 | * halts). | 1092 | * halts). |
1093 | */ | 1093 | */ |
1094 | unsigned int audit_serial(void) | 1094 | unsigned int audit_serial(void) |
1095 | { | 1095 | { |
1096 | static DEFINE_SPINLOCK(serial_lock); | 1096 | static DEFINE_SPINLOCK(serial_lock); |
1097 | static unsigned int serial = 0; | 1097 | static unsigned int serial = 0; |
1098 | 1098 | ||
1099 | unsigned long flags; | 1099 | unsigned long flags; |
1100 | unsigned int ret; | 1100 | unsigned int ret; |
1101 | 1101 | ||
1102 | spin_lock_irqsave(&serial_lock, flags); | 1102 | spin_lock_irqsave(&serial_lock, flags); |
1103 | do { | 1103 | do { |
1104 | ret = ++serial; | 1104 | ret = ++serial; |
1105 | } while (unlikely(!ret)); | 1105 | } while (unlikely(!ret)); |
1106 | spin_unlock_irqrestore(&serial_lock, flags); | 1106 | spin_unlock_irqrestore(&serial_lock, flags); |
1107 | 1107 | ||
1108 | return ret; | 1108 | return ret; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | static inline void audit_get_stamp(struct audit_context *ctx, | 1111 | static inline void audit_get_stamp(struct audit_context *ctx, |
1112 | struct timespec *t, unsigned int *serial) | 1112 | struct timespec *t, unsigned int *serial) |
1113 | { | 1113 | { |
1114 | if (!ctx || !auditsc_get_stamp(ctx, t, serial)) { | 1114 | if (!ctx || !auditsc_get_stamp(ctx, t, serial)) { |
1115 | *t = CURRENT_TIME; | 1115 | *t = CURRENT_TIME; |
1116 | *serial = audit_serial(); | 1116 | *serial = audit_serial(); |
1117 | } | 1117 | } |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | /* Obtain an audit buffer. This routine does locking to obtain the | 1120 | /* Obtain an audit buffer. This routine does locking to obtain the |
1121 | * audit buffer, but then no locking is required for calls to | 1121 | * audit buffer, but then no locking is required for calls to |
1122 | * audit_log_*format. If the tsk is a task that is currently in a | 1122 | * audit_log_*format. If the tsk is a task that is currently in a |
1123 | * syscall, then the syscall is marked as auditable and an audit record | 1123 | * syscall, then the syscall is marked as auditable and an audit record |
1124 | * will be written at syscall exit. If there is no associated task, tsk | 1124 | * will be written at syscall exit. If there is no associated task, tsk |
1125 | * should be NULL. */ | 1125 | * should be NULL. */ |
1126 | 1126 | ||
1127 | /** | 1127 | /** |
1128 | * audit_log_start - obtain an audit buffer | 1128 | * audit_log_start - obtain an audit buffer |
1129 | * @ctx: audit_context (may be NULL) | 1129 | * @ctx: audit_context (may be NULL) |
1130 | * @gfp_mask: type of allocation | 1130 | * @gfp_mask: type of allocation |
1131 | * @type: audit message type | 1131 | * @type: audit message type |
1132 | * | 1132 | * |
1133 | * Returns audit_buffer pointer on success or NULL on error. | 1133 | * Returns audit_buffer pointer on success or NULL on error. |
1134 | * | 1134 | * |
1135 | * Obtain an audit buffer. This routine does locking to obtain the | 1135 | * Obtain an audit buffer. This routine does locking to obtain the |
1136 | * audit buffer, but then no locking is required for calls to | 1136 | * audit buffer, but then no locking is required for calls to |
1137 | * audit_log_*format. If the task (ctx) is a task that is currently in a | 1137 | * audit_log_*format. If the task (ctx) is a task that is currently in a |
1138 | * syscall, then the syscall is marked as auditable and an audit record | 1138 | * syscall, then the syscall is marked as auditable and an audit record |
1139 | * will be written at syscall exit. If there is no associated task, then | 1139 | * will be written at syscall exit. If there is no associated task, then |
1140 | * task context (ctx) should be NULL. | 1140 | * task context (ctx) should be NULL. |
1141 | */ | 1141 | */ |
1142 | struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | 1142 | struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, |
1143 | int type) | 1143 | int type) |
1144 | { | 1144 | { |
1145 | struct audit_buffer *ab = NULL; | 1145 | struct audit_buffer *ab = NULL; |
1146 | struct timespec t; | 1146 | struct timespec t; |
1147 | unsigned int uninitialized_var(serial); | 1147 | unsigned int uninitialized_var(serial); |
1148 | int reserve; | 1148 | int reserve; |
1149 | unsigned long timeout_start = jiffies; | 1149 | unsigned long timeout_start = jiffies; |
1150 | 1150 | ||
1151 | if (audit_initialized != AUDIT_INITIALIZED) | 1151 | if (audit_initialized != AUDIT_INITIALIZED) |
1152 | return NULL; | 1152 | return NULL; |
1153 | 1153 | ||
1154 | if (unlikely(audit_filter_type(type))) | 1154 | if (unlikely(audit_filter_type(type))) |
1155 | return NULL; | 1155 | return NULL; |
1156 | 1156 | ||
1157 | if (gfp_mask & __GFP_WAIT) | 1157 | if (gfp_mask & __GFP_WAIT) |
1158 | reserve = 0; | 1158 | reserve = 0; |
1159 | else | 1159 | else |
1160 | reserve = 5; /* Allow atomic callers to go up to five | 1160 | reserve = 5; /* Allow atomic callers to go up to five |
1161 | entries over the normal backlog limit */ | 1161 | entries over the normal backlog limit */ |
1162 | 1162 | ||
1163 | while (audit_backlog_limit | 1163 | while (audit_backlog_limit |
1164 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { | 1164 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { |
1165 | if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time | 1165 | if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time |
1166 | && time_before(jiffies, timeout_start + audit_backlog_wait_time)) { | 1166 | && time_before(jiffies, timeout_start + audit_backlog_wait_time)) { |
1167 | 1167 | ||
1168 | /* Wait for auditd to drain the queue a little */ | 1168 | /* Wait for auditd to drain the queue a little */ |
1169 | DECLARE_WAITQUEUE(wait, current); | 1169 | DECLARE_WAITQUEUE(wait, current); |
1170 | set_current_state(TASK_INTERRUPTIBLE); | 1170 | set_current_state(TASK_INTERRUPTIBLE); |
1171 | add_wait_queue(&audit_backlog_wait, &wait); | 1171 | add_wait_queue(&audit_backlog_wait, &wait); |
1172 | 1172 | ||
1173 | if (audit_backlog_limit && | 1173 | if (audit_backlog_limit && |
1174 | skb_queue_len(&audit_skb_queue) > audit_backlog_limit) | 1174 | skb_queue_len(&audit_skb_queue) > audit_backlog_limit) |
1175 | schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies); | 1175 | schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies); |
1176 | 1176 | ||
1177 | __set_current_state(TASK_RUNNING); | 1177 | __set_current_state(TASK_RUNNING); |
1178 | remove_wait_queue(&audit_backlog_wait, &wait); | 1178 | remove_wait_queue(&audit_backlog_wait, &wait); |
1179 | continue; | 1179 | continue; |
1180 | } | 1180 | } |
1181 | if (audit_rate_check() && printk_ratelimit()) | 1181 | if (audit_rate_check() && printk_ratelimit()) |
1182 | printk(KERN_WARNING | 1182 | printk(KERN_WARNING |
1183 | "audit: audit_backlog=%d > " | 1183 | "audit: audit_backlog=%d > " |
1184 | "audit_backlog_limit=%d\n", | 1184 | "audit_backlog_limit=%d\n", |
1185 | skb_queue_len(&audit_skb_queue), | 1185 | skb_queue_len(&audit_skb_queue), |
1186 | audit_backlog_limit); | 1186 | audit_backlog_limit); |
1187 | audit_log_lost("backlog limit exceeded"); | 1187 | audit_log_lost("backlog limit exceeded"); |
1188 | audit_backlog_wait_time = audit_backlog_wait_overflow; | 1188 | audit_backlog_wait_time = audit_backlog_wait_overflow; |
1189 | wake_up(&audit_backlog_wait); | 1189 | wake_up(&audit_backlog_wait); |
1190 | return NULL; | 1190 | return NULL; |
1191 | } | 1191 | } |
1192 | 1192 | ||
1193 | ab = audit_buffer_alloc(ctx, gfp_mask, type); | 1193 | ab = audit_buffer_alloc(ctx, gfp_mask, type); |
1194 | if (!ab) { | 1194 | if (!ab) { |
1195 | audit_log_lost("out of memory in audit_log_start"); | 1195 | audit_log_lost("out of memory in audit_log_start"); |
1196 | return NULL; | 1196 | return NULL; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | audit_get_stamp(ab->ctx, &t, &serial); | 1199 | audit_get_stamp(ab->ctx, &t, &serial); |
1200 | 1200 | ||
1201 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", | 1201 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", |
1202 | t.tv_sec, t.tv_nsec/1000000, serial); | 1202 | t.tv_sec, t.tv_nsec/1000000, serial); |
1203 | return ab; | 1203 | return ab; |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | /** | 1206 | /** |
1207 | * audit_expand - expand skb in the audit buffer | 1207 | * audit_expand - expand skb in the audit buffer |
1208 | * @ab: audit_buffer | 1208 | * @ab: audit_buffer |
1209 | * @extra: space to add at tail of the skb | 1209 | * @extra: space to add at tail of the skb |
1210 | * | 1210 | * |
1211 | * Returns 0 (no space) on failed expansion, or available space if | 1211 | * Returns 0 (no space) on failed expansion, or available space if |
1212 | * successful. | 1212 | * successful. |
1213 | */ | 1213 | */ |
1214 | static inline int audit_expand(struct audit_buffer *ab, int extra) | 1214 | static inline int audit_expand(struct audit_buffer *ab, int extra) |
1215 | { | 1215 | { |
1216 | struct sk_buff *skb = ab->skb; | 1216 | struct sk_buff *skb = ab->skb; |
1217 | int oldtail = skb_tailroom(skb); | 1217 | int oldtail = skb_tailroom(skb); |
1218 | int ret = pskb_expand_head(skb, 0, extra, ab->gfp_mask); | 1218 | int ret = pskb_expand_head(skb, 0, extra, ab->gfp_mask); |
1219 | int newtail = skb_tailroom(skb); | 1219 | int newtail = skb_tailroom(skb); |
1220 | 1220 | ||
1221 | if (ret < 0) { | 1221 | if (ret < 0) { |
1222 | audit_log_lost("out of memory in audit_expand"); | 1222 | audit_log_lost("out of memory in audit_expand"); |
1223 | return 0; | 1223 | return 0; |
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | skb->truesize += newtail - oldtail; | 1226 | skb->truesize += newtail - oldtail; |
1227 | return newtail; | 1227 | return newtail; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | /* | 1230 | /* |
1231 | * Format an audit message into the audit buffer. If there isn't enough | 1231 | * Format an audit message into the audit buffer. If there isn't enough |
1232 | * room in the audit buffer, more room will be allocated and vsnprint | 1232 | * room in the audit buffer, more room will be allocated and vsnprint |
1233 | * will be called a second time. Currently, we assume that a printk | 1233 | * will be called a second time. Currently, we assume that a printk |
1234 | * can't format message larger than 1024 bytes, so we don't either. | 1234 | * can't format message larger than 1024 bytes, so we don't either. |
1235 | */ | 1235 | */ |
1236 | static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, | 1236 | static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, |
1237 | va_list args) | 1237 | va_list args) |
1238 | { | 1238 | { |
1239 | int len, avail; | 1239 | int len, avail; |
1240 | struct sk_buff *skb; | 1240 | struct sk_buff *skb; |
1241 | va_list args2; | 1241 | va_list args2; |
1242 | 1242 | ||
1243 | if (!ab) | 1243 | if (!ab) |
1244 | return; | 1244 | return; |
1245 | 1245 | ||
1246 | BUG_ON(!ab->skb); | 1246 | BUG_ON(!ab->skb); |
1247 | skb = ab->skb; | 1247 | skb = ab->skb; |
1248 | avail = skb_tailroom(skb); | 1248 | avail = skb_tailroom(skb); |
1249 | if (avail == 0) { | 1249 | if (avail == 0) { |
1250 | avail = audit_expand(ab, AUDIT_BUFSIZ); | 1250 | avail = audit_expand(ab, AUDIT_BUFSIZ); |
1251 | if (!avail) | 1251 | if (!avail) |
1252 | goto out; | 1252 | goto out; |
1253 | } | 1253 | } |
1254 | va_copy(args2, args); | 1254 | va_copy(args2, args); |
1255 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args); | 1255 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args); |
1256 | if (len >= avail) { | 1256 | if (len >= avail) { |
1257 | /* The printk buffer is 1024 bytes long, so if we get | 1257 | /* The printk buffer is 1024 bytes long, so if we get |
1258 | * here and AUDIT_BUFSIZ is at least 1024, then we can | 1258 | * here and AUDIT_BUFSIZ is at least 1024, then we can |
1259 | * log everything that printk could have logged. */ | 1259 | * log everything that printk could have logged. */ |
1260 | avail = audit_expand(ab, | 1260 | avail = audit_expand(ab, |
1261 | max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail)); | 1261 | max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail)); |
1262 | if (!avail) | 1262 | if (!avail) |
1263 | goto out; | 1263 | goto out; |
1264 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2); | 1264 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2); |
1265 | } | 1265 | } |
1266 | va_end(args2); | 1266 | va_end(args2); |
1267 | if (len > 0) | 1267 | if (len > 0) |
1268 | skb_put(skb, len); | 1268 | skb_put(skb, len); |
1269 | out: | 1269 | out: |
1270 | return; | 1270 | return; |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | /** | 1273 | /** |
1274 | * audit_log_format - format a message into the audit buffer. | 1274 | * audit_log_format - format a message into the audit buffer. |
1275 | * @ab: audit_buffer | 1275 | * @ab: audit_buffer |
1276 | * @fmt: format string | 1276 | * @fmt: format string |
1277 | * @...: optional parameters matching @fmt string | 1277 | * @...: optional parameters matching @fmt string |
1278 | * | 1278 | * |
1279 | * All the work is done in audit_log_vformat. | 1279 | * All the work is done in audit_log_vformat. |
1280 | */ | 1280 | */ |
1281 | void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) | 1281 | void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) |
1282 | { | 1282 | { |
1283 | va_list args; | 1283 | va_list args; |
1284 | 1284 | ||
1285 | if (!ab) | 1285 | if (!ab) |
1286 | return; | 1286 | return; |
1287 | va_start(args, fmt); | 1287 | va_start(args, fmt); |
1288 | audit_log_vformat(ab, fmt, args); | 1288 | audit_log_vformat(ab, fmt, args); |
1289 | va_end(args); | 1289 | va_end(args); |
1290 | } | 1290 | } |
1291 | 1291 | ||
1292 | /** | 1292 | /** |
1293 | * audit_log_hex - convert a buffer to hex and append it to the audit skb | 1293 | * audit_log_hex - convert a buffer to hex and append it to the audit skb |
1294 | * @ab: the audit_buffer | 1294 | * @ab: the audit_buffer |
1295 | * @buf: buffer to convert to hex | 1295 | * @buf: buffer to convert to hex |
1296 | * @len: length of @buf to be converted | 1296 | * @len: length of @buf to be converted |
1297 | * | 1297 | * |
1298 | * No return value; failure to expand is silently ignored. | 1298 | * No return value; failure to expand is silently ignored. |
1299 | * | 1299 | * |
1300 | * This function will take the passed buf and convert it into a string of | 1300 | * This function will take the passed buf and convert it into a string of |
1301 | * ascii hex digits. The new string is placed onto the skb. | 1301 | * ascii hex digits. The new string is placed onto the skb. |
1302 | */ | 1302 | */ |
1303 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, | 1303 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, |
1304 | size_t len) | 1304 | size_t len) |
1305 | { | 1305 | { |
1306 | int i, avail, new_len; | 1306 | int i, avail, new_len; |
1307 | unsigned char *ptr; | 1307 | unsigned char *ptr; |
1308 | struct sk_buff *skb; | 1308 | struct sk_buff *skb; |
1309 | static const unsigned char *hex = "0123456789ABCDEF"; | 1309 | static const unsigned char *hex = "0123456789ABCDEF"; |
1310 | 1310 | ||
1311 | if (!ab) | 1311 | if (!ab) |
1312 | return; | 1312 | return; |
1313 | 1313 | ||
1314 | BUG_ON(!ab->skb); | 1314 | BUG_ON(!ab->skb); |
1315 | skb = ab->skb; | 1315 | skb = ab->skb; |
1316 | avail = skb_tailroom(skb); | 1316 | avail = skb_tailroom(skb); |
1317 | new_len = len<<1; | 1317 | new_len = len<<1; |
1318 | if (new_len >= avail) { | 1318 | if (new_len >= avail) { |
1319 | /* Round the buffer request up to the next multiple */ | 1319 | /* Round the buffer request up to the next multiple */ |
1320 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); | 1320 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); |
1321 | avail = audit_expand(ab, new_len); | 1321 | avail = audit_expand(ab, new_len); |
1322 | if (!avail) | 1322 | if (!avail) |
1323 | return; | 1323 | return; |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | ptr = skb_tail_pointer(skb); | 1326 | ptr = skb_tail_pointer(skb); |
1327 | for (i=0; i<len; i++) { | 1327 | for (i=0; i<len; i++) { |
1328 | *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */ | 1328 | *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */ |
1329 | *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */ | 1329 | *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */ |
1330 | } | 1330 | } |
1331 | *ptr = 0; | 1331 | *ptr = 0; |
1332 | skb_put(skb, len << 1); /* new string is twice the old string */ | 1332 | skb_put(skb, len << 1); /* new string is twice the old string */ |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | /* | 1335 | /* |
1336 | * Format a string of no more than slen characters into the audit buffer, | 1336 | * Format a string of no more than slen characters into the audit buffer, |
1337 | * enclosed in quote marks. | 1337 | * enclosed in quote marks. |
1338 | */ | 1338 | */ |
1339 | void audit_log_n_string(struct audit_buffer *ab, const char *string, | 1339 | void audit_log_n_string(struct audit_buffer *ab, const char *string, |
1340 | size_t slen) | 1340 | size_t slen) |
1341 | { | 1341 | { |
1342 | int avail, new_len; | 1342 | int avail, new_len; |
1343 | unsigned char *ptr; | 1343 | unsigned char *ptr; |
1344 | struct sk_buff *skb; | 1344 | struct sk_buff *skb; |
1345 | 1345 | ||
1346 | if (!ab) | 1346 | if (!ab) |
1347 | return; | 1347 | return; |
1348 | 1348 | ||
1349 | BUG_ON(!ab->skb); | 1349 | BUG_ON(!ab->skb); |
1350 | skb = ab->skb; | 1350 | skb = ab->skb; |
1351 | avail = skb_tailroom(skb); | 1351 | avail = skb_tailroom(skb); |
1352 | new_len = slen + 3; /* enclosing quotes + null terminator */ | 1352 | new_len = slen + 3; /* enclosing quotes + null terminator */ |
1353 | if (new_len > avail) { | 1353 | if (new_len > avail) { |
1354 | avail = audit_expand(ab, new_len); | 1354 | avail = audit_expand(ab, new_len); |
1355 | if (!avail) | 1355 | if (!avail) |
1356 | return; | 1356 | return; |
1357 | } | 1357 | } |
1358 | ptr = skb_tail_pointer(skb); | 1358 | ptr = skb_tail_pointer(skb); |
1359 | *ptr++ = '"'; | 1359 | *ptr++ = '"'; |
1360 | memcpy(ptr, string, slen); | 1360 | memcpy(ptr, string, slen); |
1361 | ptr += slen; | 1361 | ptr += slen; |
1362 | *ptr++ = '"'; | 1362 | *ptr++ = '"'; |
1363 | *ptr = 0; | 1363 | *ptr = 0; |
1364 | skb_put(skb, slen + 2); /* don't include null terminator */ | 1364 | skb_put(skb, slen + 2); /* don't include null terminator */ |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | /** | 1367 | /** |
1368 | * audit_string_contains_control - does a string need to be logged in hex | 1368 | * audit_string_contains_control - does a string need to be logged in hex |
1369 | * @string: string to be checked | 1369 | * @string: string to be checked |
1370 | * @len: max length of the string to check | 1370 | * @len: max length of the string to check |
1371 | */ | 1371 | */ |
1372 | int audit_string_contains_control(const char *string, size_t len) | 1372 | int audit_string_contains_control(const char *string, size_t len) |
1373 | { | 1373 | { |
1374 | const unsigned char *p; | 1374 | const unsigned char *p; |
1375 | for (p = string; p < (const unsigned char *)string + len; p++) { | 1375 | for (p = string; p < (const unsigned char *)string + len; p++) { |
1376 | if (*p == '"' || *p < 0x21 || *p > 0x7e) | 1376 | if (*p == '"' || *p < 0x21 || *p > 0x7e) |
1377 | return 1; | 1377 | return 1; |
1378 | } | 1378 | } |
1379 | return 0; | 1379 | return 0; |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | /** | 1382 | /** |
1383 | * audit_log_n_untrustedstring - log a string that may contain random characters | 1383 | * audit_log_n_untrustedstring - log a string that may contain random characters |
1384 | * @ab: audit_buffer | 1384 | * @ab: audit_buffer |
1385 | * @len: length of string (not including trailing null) | 1385 | * @len: length of string (not including trailing null) |
1386 | * @string: string to be logged | 1386 | * @string: string to be logged |
1387 | * | 1387 | * |
1388 | * This code will escape a string that is passed to it if the string | 1388 | * This code will escape a string that is passed to it if the string |
1389 | * contains a control character, unprintable character, double quote mark, | 1389 | * contains a control character, unprintable character, double quote mark, |
1390 | * or a space. Unescaped strings will start and end with a double quote mark. | 1390 | * or a space. Unescaped strings will start and end with a double quote mark. |
1391 | * Strings that are escaped are printed in hex (2 digits per char). | 1391 | * Strings that are escaped are printed in hex (2 digits per char). |
1392 | * | 1392 | * |
1393 | * The caller specifies the number of characters in the string to log, which may | 1393 | * The caller specifies the number of characters in the string to log, which may |
1394 | * or may not be the entire string. | 1394 | * or may not be the entire string. |
1395 | */ | 1395 | */ |
1396 | void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string, | 1396 | void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string, |
1397 | size_t len) | 1397 | size_t len) |
1398 | { | 1398 | { |
1399 | if (audit_string_contains_control(string, len)) | 1399 | if (audit_string_contains_control(string, len)) |
1400 | audit_log_n_hex(ab, string, len); | 1400 | audit_log_n_hex(ab, string, len); |
1401 | else | 1401 | else |
1402 | audit_log_n_string(ab, string, len); | 1402 | audit_log_n_string(ab, string, len); |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | /** | 1405 | /** |
1406 | * audit_log_untrustedstring - log a string that may contain random characters | 1406 | * audit_log_untrustedstring - log a string that may contain random characters |
1407 | * @ab: audit_buffer | 1407 | * @ab: audit_buffer |
1408 | * @string: string to be logged | 1408 | * @string: string to be logged |
1409 | * | 1409 | * |
1410 | * Same as audit_log_n_untrustedstring(), except that strlen is used to | 1410 | * Same as audit_log_n_untrustedstring(), except that strlen is used to |
1411 | * determine string length. | 1411 | * determine string length. |
1412 | */ | 1412 | */ |
1413 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1413 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
1414 | { | 1414 | { |
1415 | audit_log_n_untrustedstring(ab, string, strlen(string)); | 1415 | audit_log_n_untrustedstring(ab, string, strlen(string)); |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | /* This is a helper-function to print the escaped d_path */ | 1418 | /* This is a helper-function to print the escaped d_path */ |
1419 | void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | 1419 | void audit_log_d_path(struct audit_buffer *ab, const char *prefix, |
1420 | struct path *path) | 1420 | struct path *path) |
1421 | { | 1421 | { |
1422 | char *p, *pathname; | 1422 | char *p, *pathname; |
1423 | 1423 | ||
1424 | if (prefix) | 1424 | if (prefix) |
1425 | audit_log_format(ab, " %s", prefix); | 1425 | audit_log_format(ab, " %s", prefix); |
1426 | 1426 | ||
1427 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 1427 | /* We will allow 11 spaces for ' (deleted)' to be appended */ |
1428 | pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); | 1428 | pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); |
1429 | if (!pathname) { | 1429 | if (!pathname) { |
1430 | audit_log_string(ab, "<no_memory>"); | 1430 | audit_log_string(ab, "<no_memory>"); |
1431 | return; | 1431 | return; |
1432 | } | 1432 | } |
1433 | p = d_path(path, pathname, PATH_MAX+11); | 1433 | p = d_path(path, pathname, PATH_MAX+11); |
1434 | if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ | 1434 | if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ |
1435 | /* FIXME: can we save some information here? */ | 1435 | /* FIXME: can we save some information here? */ |
1436 | audit_log_string(ab, "<too_long>"); | 1436 | audit_log_string(ab, "<too_long>"); |
1437 | } else | 1437 | } else |
1438 | audit_log_untrustedstring(ab, p); | 1438 | audit_log_untrustedstring(ab, p); |
1439 | kfree(pathname); | 1439 | kfree(pathname); |
1440 | } | 1440 | } |
1441 | 1441 | ||
1442 | void audit_log_key(struct audit_buffer *ab, char *key) | 1442 | void audit_log_key(struct audit_buffer *ab, char *key) |
1443 | { | 1443 | { |
1444 | audit_log_format(ab, " key="); | 1444 | audit_log_format(ab, " key="); |
1445 | if (key) | 1445 | if (key) |
1446 | audit_log_untrustedstring(ab, key); | 1446 | audit_log_untrustedstring(ab, key); |
1447 | else | 1447 | else |
1448 | audit_log_format(ab, "(null)"); | 1448 | audit_log_format(ab, "(null)"); |
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | /** | 1451 | /** |
1452 | * audit_log_end - end one audit record | 1452 | * audit_log_end - end one audit record |
1453 | * @ab: the audit_buffer | 1453 | * @ab: the audit_buffer |
1454 | * | 1454 | * |
1455 | * The netlink_* functions cannot be called inside an irq context, so | 1455 | * The netlink_* functions cannot be called inside an irq context, so |
1456 | * the audit buffer is placed on a queue and a tasklet is scheduled to | 1456 | * the audit buffer is placed on a queue and a tasklet is scheduled to |
1457 | * remove them from the queue outside the irq context. May be called in | 1457 | * remove them from the queue outside the irq context. May be called in |
1458 | * any context. | 1458 | * any context. |
1459 | */ | 1459 | */ |
1460 | void audit_log_end(struct audit_buffer *ab) | 1460 | void audit_log_end(struct audit_buffer *ab) |
1461 | { | 1461 | { |
1462 | if (!ab) | 1462 | if (!ab) |
1463 | return; | 1463 | return; |
1464 | if (!audit_rate_check()) { | 1464 | if (!audit_rate_check()) { |
1465 | audit_log_lost("rate limit exceeded"); | 1465 | audit_log_lost("rate limit exceeded"); |
1466 | } else { | 1466 | } else { |
1467 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 1467 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
1468 | nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0); | 1468 | nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0); |
1469 | 1469 | ||
1470 | if (audit_pid) { | 1470 | if (audit_pid) { |
1471 | skb_queue_tail(&audit_skb_queue, ab->skb); | 1471 | skb_queue_tail(&audit_skb_queue, ab->skb); |
1472 | wake_up_interruptible(&kauditd_wait); | 1472 | wake_up_interruptible(&kauditd_wait); |
1473 | } else { | 1473 | } else { |
1474 | audit_printk_skb(ab->skb); | 1474 | audit_printk_skb(ab->skb); |
1475 | } | 1475 | } |
1476 | ab->skb = NULL; | 1476 | ab->skb = NULL; |
1477 | } | 1477 | } |
1478 | audit_buffer_free(ab); | 1478 | audit_buffer_free(ab); |
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | /** | 1481 | /** |
1482 | * audit_log - Log an audit record | 1482 | * audit_log - Log an audit record |
1483 | * @ctx: audit context | 1483 | * @ctx: audit context |
1484 | * @gfp_mask: type of allocation | 1484 | * @gfp_mask: type of allocation |
1485 | * @type: audit message type | 1485 | * @type: audit message type |
1486 | * @fmt: format string to use | 1486 | * @fmt: format string to use |
1487 | * @...: variable parameters matching the format string | 1487 | * @...: variable parameters matching the format string |
1488 | * | 1488 | * |
1489 | * This is a convenience function that calls audit_log_start, | 1489 | * This is a convenience function that calls audit_log_start, |
1490 | * audit_log_vformat, and audit_log_end. It may be called | 1490 | * audit_log_vformat, and audit_log_end. It may be called |
1491 | * in any context. | 1491 | * in any context. |
1492 | */ | 1492 | */ |
1493 | void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, | 1493 | void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, |
1494 | const char *fmt, ...) | 1494 | const char *fmt, ...) |
1495 | { | 1495 | { |
1496 | struct audit_buffer *ab; | 1496 | struct audit_buffer *ab; |
1497 | va_list args; | 1497 | va_list args; |
1498 | 1498 | ||
1499 | ab = audit_log_start(ctx, gfp_mask, type); | 1499 | ab = audit_log_start(ctx, gfp_mask, type); |
1500 | if (ab) { | 1500 | if (ab) { |
1501 | va_start(args, fmt); | 1501 | va_start(args, fmt); |
1502 | audit_log_vformat(ab, fmt, args); | 1502 | audit_log_vformat(ab, fmt, args); |
1503 | va_end(args); | 1503 | va_end(args); |
1504 | audit_log_end(ab); | 1504 | audit_log_end(ab); |
1505 | } | 1505 | } |
1506 | } | 1506 | } |
1507 | 1507 | ||
1508 | #ifdef CONFIG_SECURITY | 1508 | #ifdef CONFIG_SECURITY |
1509 | /** | 1509 | /** |
1510 | * audit_log_secctx - Converts and logs SELinux context | 1510 | * audit_log_secctx - Converts and logs SELinux context |
1511 | * @ab: audit_buffer | 1511 | * @ab: audit_buffer |
1512 | * @secid: security number | 1512 | * @secid: security number |
1513 | * | 1513 | * |
1514 | * This is a helper function that calls security_secid_to_secctx to convert | 1514 | * This is a helper function that calls security_secid_to_secctx to convert |
1515 | * secid to secctx and then adds the (converted) SELinux context to the audit | 1515 | * secid to secctx and then adds the (converted) SELinux context to the audit |
1516 | * log by calling audit_log_format, thus also preventing leak of internal secid | 1516 | * log by calling audit_log_format, thus also preventing leak of internal secid |
1517 | * to userspace. If secid cannot be converted audit_panic is called. | 1517 | * to userspace. If secid cannot be converted audit_panic is called. |
1518 | */ | 1518 | */ |
1519 | void audit_log_secctx(struct audit_buffer *ab, u32 secid) | 1519 | void audit_log_secctx(struct audit_buffer *ab, u32 secid) |
1520 | { | 1520 | { |
1521 | u32 len; | 1521 | u32 len; |
1522 | char *secctx; | 1522 | char *secctx; |
1523 | 1523 | ||
1524 | if (security_secid_to_secctx(secid, &secctx, &len)) { | 1524 | if (security_secid_to_secctx(secid, &secctx, &len)) { |
1525 | audit_panic("Cannot convert secid to context"); | 1525 | audit_panic("Cannot convert secid to context"); |
1526 | } else { | 1526 | } else { |
1527 | audit_log_format(ab, " obj=%s", secctx); | 1527 | audit_log_format(ab, " obj=%s", secctx); |
1528 | security_release_secctx(secctx, len); | 1528 | security_release_secctx(secctx, len); |
1529 | } | 1529 | } |
1530 | } | 1530 | } |
1531 | EXPORT_SYMBOL(audit_log_secctx); | 1531 | EXPORT_SYMBOL(audit_log_secctx); |
1532 | #endif | 1532 | #endif |
1533 | 1533 | ||
1534 | EXPORT_SYMBOL(audit_log_start); | 1534 | EXPORT_SYMBOL(audit_log_start); |
1535 | EXPORT_SYMBOL(audit_log_end); | 1535 | EXPORT_SYMBOL(audit_log_end); |
1536 | EXPORT_SYMBOL(audit_log_format); | 1536 | EXPORT_SYMBOL(audit_log_format); |
1537 | EXPORT_SYMBOL(audit_log); | 1537 | EXPORT_SYMBOL(audit_log); |
1538 | 1538 |
net/core/rtnetlink.c
1 | /* | 1 | /* |
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | 2 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
3 | * operating system. INET is implemented using the BSD Socket | 3 | * operating system. INET is implemented using the BSD Socket |
4 | * interface as the means of communication with the user level. | 4 | * interface as the means of communication with the user level. |
5 | * | 5 | * |
6 | * Routing netlink socket interface: protocol independent part. | 6 | * Routing netlink socket interface: protocol independent part. |
7 | * | 7 | * |
8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
13 | * 2 of the License, or (at your option) any later version. | 13 | * 2 of the License, or (at your option) any later version. |
14 | * | 14 | * |
15 | * Fixes: | 15 | * Fixes: |
16 | * Vitaly E. Lavrov RTA_OK arithmetics was wrong. | 16 | * Vitaly E. Lavrov RTA_OK arithmetics was wrong. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/socket.h> | 22 | #include <linux/socket.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/sockios.h> | 26 | #include <linux/sockios.h> |
27 | #include <linux/net.h> | 27 | #include <linux/net.h> |
28 | #include <linux/fcntl.h> | 28 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/capability.h> | 32 | #include <linux/capability.h> |
33 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/security.h> | 35 | #include <linux/security.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/if_addr.h> | 37 | #include <linux/if_addr.h> |
38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
39 | 39 | ||
40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | 42 | ||
43 | #include <linux/inet.h> | 43 | #include <linux/inet.h> |
44 | #include <linux/netdevice.h> | 44 | #include <linux/netdevice.h> |
45 | #include <net/ip.h> | 45 | #include <net/ip.h> |
46 | #include <net/protocol.h> | 46 | #include <net/protocol.h> |
47 | #include <net/arp.h> | 47 | #include <net/arp.h> |
48 | #include <net/route.h> | 48 | #include <net/route.h> |
49 | #include <net/udp.h> | 49 | #include <net/udp.h> |
50 | #include <net/sock.h> | 50 | #include <net/sock.h> |
51 | #include <net/pkt_sched.h> | 51 | #include <net/pkt_sched.h> |
52 | #include <net/fib_rules.h> | 52 | #include <net/fib_rules.h> |
53 | #include <net/rtnetlink.h> | 53 | #include <net/rtnetlink.h> |
54 | #include <net/net_namespace.h> | 54 | #include <net/net_namespace.h> |
55 | 55 | ||
56 | struct rtnl_link { | 56 | struct rtnl_link { |
57 | rtnl_doit_func doit; | 57 | rtnl_doit_func doit; |
58 | rtnl_dumpit_func dumpit; | 58 | rtnl_dumpit_func dumpit; |
59 | rtnl_calcit_func calcit; | 59 | rtnl_calcit_func calcit; |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static DEFINE_MUTEX(rtnl_mutex); | 62 | static DEFINE_MUTEX(rtnl_mutex); |
63 | static u16 min_ifinfo_dump_size; | 63 | static u16 min_ifinfo_dump_size; |
64 | 64 | ||
65 | void rtnl_lock(void) | 65 | void rtnl_lock(void) |
66 | { | 66 | { |
67 | mutex_lock(&rtnl_mutex); | 67 | mutex_lock(&rtnl_mutex); |
68 | } | 68 | } |
69 | EXPORT_SYMBOL(rtnl_lock); | 69 | EXPORT_SYMBOL(rtnl_lock); |
70 | 70 | ||
71 | void __rtnl_unlock(void) | 71 | void __rtnl_unlock(void) |
72 | { | 72 | { |
73 | mutex_unlock(&rtnl_mutex); | 73 | mutex_unlock(&rtnl_mutex); |
74 | } | 74 | } |
75 | 75 | ||
76 | void rtnl_unlock(void) | 76 | void rtnl_unlock(void) |
77 | { | 77 | { |
78 | /* This fellow will unlock it for us. */ | 78 | /* This fellow will unlock it for us. */ |
79 | netdev_run_todo(); | 79 | netdev_run_todo(); |
80 | } | 80 | } |
81 | EXPORT_SYMBOL(rtnl_unlock); | 81 | EXPORT_SYMBOL(rtnl_unlock); |
82 | 82 | ||
83 | int rtnl_trylock(void) | 83 | int rtnl_trylock(void) |
84 | { | 84 | { |
85 | return mutex_trylock(&rtnl_mutex); | 85 | return mutex_trylock(&rtnl_mutex); |
86 | } | 86 | } |
87 | EXPORT_SYMBOL(rtnl_trylock); | 87 | EXPORT_SYMBOL(rtnl_trylock); |
88 | 88 | ||
89 | int rtnl_is_locked(void) | 89 | int rtnl_is_locked(void) |
90 | { | 90 | { |
91 | return mutex_is_locked(&rtnl_mutex); | 91 | return mutex_is_locked(&rtnl_mutex); |
92 | } | 92 | } |
93 | EXPORT_SYMBOL(rtnl_is_locked); | 93 | EXPORT_SYMBOL(rtnl_is_locked); |
94 | 94 | ||
95 | #ifdef CONFIG_PROVE_LOCKING | 95 | #ifdef CONFIG_PROVE_LOCKING |
96 | int lockdep_rtnl_is_held(void) | 96 | int lockdep_rtnl_is_held(void) |
97 | { | 97 | { |
98 | return lockdep_is_held(&rtnl_mutex); | 98 | return lockdep_is_held(&rtnl_mutex); |
99 | } | 99 | } |
100 | EXPORT_SYMBOL(lockdep_rtnl_is_held); | 100 | EXPORT_SYMBOL(lockdep_rtnl_is_held); |
101 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ | 101 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ |
102 | 102 | ||
103 | static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; | 103 | static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; |
104 | 104 | ||
105 | static inline int rtm_msgindex(int msgtype) | 105 | static inline int rtm_msgindex(int msgtype) |
106 | { | 106 | { |
107 | int msgindex = msgtype - RTM_BASE; | 107 | int msgindex = msgtype - RTM_BASE; |
108 | 108 | ||
109 | /* | 109 | /* |
110 | * msgindex < 0 implies someone tried to register a netlink | 110 | * msgindex < 0 implies someone tried to register a netlink |
111 | * control code. msgindex >= RTM_NR_MSGTYPES may indicate that | 111 | * control code. msgindex >= RTM_NR_MSGTYPES may indicate that |
112 | * the message type has not been added to linux/rtnetlink.h | 112 | * the message type has not been added to linux/rtnetlink.h |
113 | */ | 113 | */ |
114 | BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); | 114 | BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); |
115 | 115 | ||
116 | return msgindex; | 116 | return msgindex; |
117 | } | 117 | } |
118 | 118 | ||
119 | static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) | 119 | static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) |
120 | { | 120 | { |
121 | struct rtnl_link *tab; | 121 | struct rtnl_link *tab; |
122 | 122 | ||
123 | if (protocol <= RTNL_FAMILY_MAX) | 123 | if (protocol <= RTNL_FAMILY_MAX) |
124 | tab = rtnl_msg_handlers[protocol]; | 124 | tab = rtnl_msg_handlers[protocol]; |
125 | else | 125 | else |
126 | tab = NULL; | 126 | tab = NULL; |
127 | 127 | ||
128 | if (tab == NULL || tab[msgindex].doit == NULL) | 128 | if (tab == NULL || tab[msgindex].doit == NULL) |
129 | tab = rtnl_msg_handlers[PF_UNSPEC]; | 129 | tab = rtnl_msg_handlers[PF_UNSPEC]; |
130 | 130 | ||
131 | return tab ? tab[msgindex].doit : NULL; | 131 | return tab ? tab[msgindex].doit : NULL; |
132 | } | 132 | } |
133 | 133 | ||
134 | static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) | 134 | static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) |
135 | { | 135 | { |
136 | struct rtnl_link *tab; | 136 | struct rtnl_link *tab; |
137 | 137 | ||
138 | if (protocol <= RTNL_FAMILY_MAX) | 138 | if (protocol <= RTNL_FAMILY_MAX) |
139 | tab = rtnl_msg_handlers[protocol]; | 139 | tab = rtnl_msg_handlers[protocol]; |
140 | else | 140 | else |
141 | tab = NULL; | 141 | tab = NULL; |
142 | 142 | ||
143 | if (tab == NULL || tab[msgindex].dumpit == NULL) | 143 | if (tab == NULL || tab[msgindex].dumpit == NULL) |
144 | tab = rtnl_msg_handlers[PF_UNSPEC]; | 144 | tab = rtnl_msg_handlers[PF_UNSPEC]; |
145 | 145 | ||
146 | return tab ? tab[msgindex].dumpit : NULL; | 146 | return tab ? tab[msgindex].dumpit : NULL; |
147 | } | 147 | } |
148 | 148 | ||
149 | static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex) | 149 | static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex) |
150 | { | 150 | { |
151 | struct rtnl_link *tab; | 151 | struct rtnl_link *tab; |
152 | 152 | ||
153 | if (protocol <= RTNL_FAMILY_MAX) | 153 | if (protocol <= RTNL_FAMILY_MAX) |
154 | tab = rtnl_msg_handlers[protocol]; | 154 | tab = rtnl_msg_handlers[protocol]; |
155 | else | 155 | else |
156 | tab = NULL; | 156 | tab = NULL; |
157 | 157 | ||
158 | if (tab == NULL || tab[msgindex].calcit == NULL) | 158 | if (tab == NULL || tab[msgindex].calcit == NULL) |
159 | tab = rtnl_msg_handlers[PF_UNSPEC]; | 159 | tab = rtnl_msg_handlers[PF_UNSPEC]; |
160 | 160 | ||
161 | return tab ? tab[msgindex].calcit : NULL; | 161 | return tab ? tab[msgindex].calcit : NULL; |
162 | } | 162 | } |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * __rtnl_register - Register a rtnetlink message type | 165 | * __rtnl_register - Register a rtnetlink message type |
166 | * @protocol: Protocol family or PF_UNSPEC | 166 | * @protocol: Protocol family or PF_UNSPEC |
167 | * @msgtype: rtnetlink message type | 167 | * @msgtype: rtnetlink message type |
168 | * @doit: Function pointer called for each request message | 168 | * @doit: Function pointer called for each request message |
169 | * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message | 169 | * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
170 | * @calcit: Function pointer to calc size of dump message | 170 | * @calcit: Function pointer to calc size of dump message |
171 | * | 171 | * |
172 | * Registers the specified function pointers (at least one of them has | 172 | * Registers the specified function pointers (at least one of them has |
173 | * to be non-NULL) to be called whenever a request message for the | 173 | * to be non-NULL) to be called whenever a request message for the |
174 | * specified protocol family and message type is received. | 174 | * specified protocol family and message type is received. |
175 | * | 175 | * |
176 | * The special protocol family PF_UNSPEC may be used to define fallback | 176 | * The special protocol family PF_UNSPEC may be used to define fallback |
177 | * function pointers for the case when no entry for the specific protocol | 177 | * function pointers for the case when no entry for the specific protocol |
178 | * family exists. | 178 | * family exists. |
179 | * | 179 | * |
180 | * Returns 0 on success or a negative error code. | 180 | * Returns 0 on success or a negative error code. |
181 | */ | 181 | */ |
182 | int __rtnl_register(int protocol, int msgtype, | 182 | int __rtnl_register(int protocol, int msgtype, |
183 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, | 183 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
184 | rtnl_calcit_func calcit) | 184 | rtnl_calcit_func calcit) |
185 | { | 185 | { |
186 | struct rtnl_link *tab; | 186 | struct rtnl_link *tab; |
187 | int msgindex; | 187 | int msgindex; |
188 | 188 | ||
189 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); | 189 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
190 | msgindex = rtm_msgindex(msgtype); | 190 | msgindex = rtm_msgindex(msgtype); |
191 | 191 | ||
192 | tab = rtnl_msg_handlers[protocol]; | 192 | tab = rtnl_msg_handlers[protocol]; |
193 | if (tab == NULL) { | 193 | if (tab == NULL) { |
194 | tab = kcalloc(RTM_NR_MSGTYPES, sizeof(*tab), GFP_KERNEL); | 194 | tab = kcalloc(RTM_NR_MSGTYPES, sizeof(*tab), GFP_KERNEL); |
195 | if (tab == NULL) | 195 | if (tab == NULL) |
196 | return -ENOBUFS; | 196 | return -ENOBUFS; |
197 | 197 | ||
198 | rtnl_msg_handlers[protocol] = tab; | 198 | rtnl_msg_handlers[protocol] = tab; |
199 | } | 199 | } |
200 | 200 | ||
201 | if (doit) | 201 | if (doit) |
202 | tab[msgindex].doit = doit; | 202 | tab[msgindex].doit = doit; |
203 | 203 | ||
204 | if (dumpit) | 204 | if (dumpit) |
205 | tab[msgindex].dumpit = dumpit; | 205 | tab[msgindex].dumpit = dumpit; |
206 | 206 | ||
207 | if (calcit) | 207 | if (calcit) |
208 | tab[msgindex].calcit = calcit; | 208 | tab[msgindex].calcit = calcit; |
209 | 209 | ||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | EXPORT_SYMBOL_GPL(__rtnl_register); | 212 | EXPORT_SYMBOL_GPL(__rtnl_register); |
213 | 213 | ||
214 | /** | 214 | /** |
215 | * rtnl_register - Register a rtnetlink message type | 215 | * rtnl_register - Register a rtnetlink message type |
216 | * | 216 | * |
217 | * Identical to __rtnl_register() but panics on failure. This is useful | 217 | * Identical to __rtnl_register() but panics on failure. This is useful |
218 | * as failure of this function is very unlikely, it can only happen due | 218 | * as failure of this function is very unlikely, it can only happen due |
219 | * to lack of memory when allocating the chain to store all message | 219 | * to lack of memory when allocating the chain to store all message |
220 | * handlers for a protocol. Meant for use in init functions where lack | 220 | * handlers for a protocol. Meant for use in init functions where lack |
221 | * of memory implies no sense in continuing. | 221 | * of memory implies no sense in continuing. |
222 | */ | 222 | */ |
223 | void rtnl_register(int protocol, int msgtype, | 223 | void rtnl_register(int protocol, int msgtype, |
224 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, | 224 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
225 | rtnl_calcit_func calcit) | 225 | rtnl_calcit_func calcit) |
226 | { | 226 | { |
227 | if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0) | 227 | if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0) |
228 | panic("Unable to register rtnetlink message handler, " | 228 | panic("Unable to register rtnetlink message handler, " |
229 | "protocol = %d, message type = %d\n", | 229 | "protocol = %d, message type = %d\n", |
230 | protocol, msgtype); | 230 | protocol, msgtype); |
231 | } | 231 | } |
232 | EXPORT_SYMBOL_GPL(rtnl_register); | 232 | EXPORT_SYMBOL_GPL(rtnl_register); |
233 | 233 | ||
234 | /** | 234 | /** |
235 | * rtnl_unregister - Unregister a rtnetlink message type | 235 | * rtnl_unregister - Unregister a rtnetlink message type |
236 | * @protocol: Protocol family or PF_UNSPEC | 236 | * @protocol: Protocol family or PF_UNSPEC |
237 | * @msgtype: rtnetlink message type | 237 | * @msgtype: rtnetlink message type |
238 | * | 238 | * |
239 | * Returns 0 on success or a negative error code. | 239 | * Returns 0 on success or a negative error code. |
240 | */ | 240 | */ |
241 | int rtnl_unregister(int protocol, int msgtype) | 241 | int rtnl_unregister(int protocol, int msgtype) |
242 | { | 242 | { |
243 | int msgindex; | 243 | int msgindex; |
244 | 244 | ||
245 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); | 245 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
246 | msgindex = rtm_msgindex(msgtype); | 246 | msgindex = rtm_msgindex(msgtype); |
247 | 247 | ||
248 | if (rtnl_msg_handlers[protocol] == NULL) | 248 | if (rtnl_msg_handlers[protocol] == NULL) |
249 | return -ENOENT; | 249 | return -ENOENT; |
250 | 250 | ||
251 | rtnl_msg_handlers[protocol][msgindex].doit = NULL; | 251 | rtnl_msg_handlers[protocol][msgindex].doit = NULL; |
252 | rtnl_msg_handlers[protocol][msgindex].dumpit = NULL; | 252 | rtnl_msg_handlers[protocol][msgindex].dumpit = NULL; |
253 | 253 | ||
254 | return 0; | 254 | return 0; |
255 | } | 255 | } |
256 | EXPORT_SYMBOL_GPL(rtnl_unregister); | 256 | EXPORT_SYMBOL_GPL(rtnl_unregister); |
257 | 257 | ||
258 | /** | 258 | /** |
259 | * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol | 259 | * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol |
260 | * @protocol : Protocol family or PF_UNSPEC | 260 | * @protocol : Protocol family or PF_UNSPEC |
261 | * | 261 | * |
262 | * Identical to calling rtnl_unregster() for all registered message types | 262 | * Identical to calling rtnl_unregster() for all registered message types |
263 | * of a certain protocol family. | 263 | * of a certain protocol family. |
264 | */ | 264 | */ |
265 | void rtnl_unregister_all(int protocol) | 265 | void rtnl_unregister_all(int protocol) |
266 | { | 266 | { |
267 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); | 267 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
268 | 268 | ||
269 | kfree(rtnl_msg_handlers[protocol]); | 269 | kfree(rtnl_msg_handlers[protocol]); |
270 | rtnl_msg_handlers[protocol] = NULL; | 270 | rtnl_msg_handlers[protocol] = NULL; |
271 | } | 271 | } |
272 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); | 272 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
273 | 273 | ||
274 | static LIST_HEAD(link_ops); | 274 | static LIST_HEAD(link_ops); |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. | 277 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. |
278 | * @ops: struct rtnl_link_ops * to register | 278 | * @ops: struct rtnl_link_ops * to register |
279 | * | 279 | * |
280 | * The caller must hold the rtnl_mutex. This function should be used | 280 | * The caller must hold the rtnl_mutex. This function should be used |
281 | * by drivers that create devices during module initialization. It | 281 | * by drivers that create devices during module initialization. It |
282 | * must be called before registering the devices. | 282 | * must be called before registering the devices. |
283 | * | 283 | * |
284 | * Returns 0 on success or a negative error code. | 284 | * Returns 0 on success or a negative error code. |
285 | */ | 285 | */ |
286 | int __rtnl_link_register(struct rtnl_link_ops *ops) | 286 | int __rtnl_link_register(struct rtnl_link_ops *ops) |
287 | { | 287 | { |
288 | if (!ops->dellink) | 288 | if (!ops->dellink) |
289 | ops->dellink = unregister_netdevice_queue; | 289 | ops->dellink = unregister_netdevice_queue; |
290 | 290 | ||
291 | list_add_tail(&ops->list, &link_ops); | 291 | list_add_tail(&ops->list, &link_ops); |
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
294 | EXPORT_SYMBOL_GPL(__rtnl_link_register); | 294 | EXPORT_SYMBOL_GPL(__rtnl_link_register); |
295 | 295 | ||
296 | /** | 296 | /** |
297 | * rtnl_link_register - Register rtnl_link_ops with rtnetlink. | 297 | * rtnl_link_register - Register rtnl_link_ops with rtnetlink. |
298 | * @ops: struct rtnl_link_ops * to register | 298 | * @ops: struct rtnl_link_ops * to register |
299 | * | 299 | * |
300 | * Returns 0 on success or a negative error code. | 300 | * Returns 0 on success or a negative error code. |
301 | */ | 301 | */ |
302 | int rtnl_link_register(struct rtnl_link_ops *ops) | 302 | int rtnl_link_register(struct rtnl_link_ops *ops) |
303 | { | 303 | { |
304 | int err; | 304 | int err; |
305 | 305 | ||
306 | rtnl_lock(); | 306 | rtnl_lock(); |
307 | err = __rtnl_link_register(ops); | 307 | err = __rtnl_link_register(ops); |
308 | rtnl_unlock(); | 308 | rtnl_unlock(); |
309 | return err; | 309 | return err; |
310 | } | 310 | } |
311 | EXPORT_SYMBOL_GPL(rtnl_link_register); | 311 | EXPORT_SYMBOL_GPL(rtnl_link_register); |
312 | 312 | ||
313 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | 313 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) |
314 | { | 314 | { |
315 | struct net_device *dev; | 315 | struct net_device *dev; |
316 | LIST_HEAD(list_kill); | 316 | LIST_HEAD(list_kill); |
317 | 317 | ||
318 | for_each_netdev(net, dev) { | 318 | for_each_netdev(net, dev) { |
319 | if (dev->rtnl_link_ops == ops) | 319 | if (dev->rtnl_link_ops == ops) |
320 | ops->dellink(dev, &list_kill); | 320 | ops->dellink(dev, &list_kill); |
321 | } | 321 | } |
322 | unregister_netdevice_many(&list_kill); | 322 | unregister_netdevice_many(&list_kill); |
323 | } | 323 | } |
324 | 324 | ||
325 | /** | 325 | /** |
326 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | 326 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. |
327 | * @ops: struct rtnl_link_ops * to unregister | 327 | * @ops: struct rtnl_link_ops * to unregister |
328 | * | 328 | * |
329 | * The caller must hold the rtnl_mutex. | 329 | * The caller must hold the rtnl_mutex. |
330 | */ | 330 | */ |
331 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) | 331 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) |
332 | { | 332 | { |
333 | struct net *net; | 333 | struct net *net; |
334 | 334 | ||
335 | for_each_net(net) { | 335 | for_each_net(net) { |
336 | __rtnl_kill_links(net, ops); | 336 | __rtnl_kill_links(net, ops); |
337 | } | 337 | } |
338 | list_del(&ops->list); | 338 | list_del(&ops->list); |
339 | } | 339 | } |
340 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 340 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
341 | 341 | ||
342 | /** | 342 | /** |
343 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | 343 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. |
344 | * @ops: struct rtnl_link_ops * to unregister | 344 | * @ops: struct rtnl_link_ops * to unregister |
345 | */ | 345 | */ |
346 | void rtnl_link_unregister(struct rtnl_link_ops *ops) | 346 | void rtnl_link_unregister(struct rtnl_link_ops *ops) |
347 | { | 347 | { |
348 | rtnl_lock(); | 348 | rtnl_lock(); |
349 | __rtnl_link_unregister(ops); | 349 | __rtnl_link_unregister(ops); |
350 | rtnl_unlock(); | 350 | rtnl_unlock(); |
351 | } | 351 | } |
352 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 352 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
353 | 353 | ||
354 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | 354 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) |
355 | { | 355 | { |
356 | const struct rtnl_link_ops *ops; | 356 | const struct rtnl_link_ops *ops; |
357 | 357 | ||
358 | list_for_each_entry(ops, &link_ops, list) { | 358 | list_for_each_entry(ops, &link_ops, list) { |
359 | if (!strcmp(ops->kind, kind)) | 359 | if (!strcmp(ops->kind, kind)) |
360 | return ops; | 360 | return ops; |
361 | } | 361 | } |
362 | return NULL; | 362 | return NULL; |
363 | } | 363 | } |
364 | 364 | ||
365 | static size_t rtnl_link_get_size(const struct net_device *dev) | 365 | static size_t rtnl_link_get_size(const struct net_device *dev) |
366 | { | 366 | { |
367 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | 367 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; |
368 | size_t size; | 368 | size_t size; |
369 | 369 | ||
370 | if (!ops) | 370 | if (!ops) |
371 | return 0; | 371 | return 0; |
372 | 372 | ||
373 | size = nla_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ | 373 | size = nla_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ |
374 | nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ | 374 | nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ |
375 | 375 | ||
376 | if (ops->get_size) | 376 | if (ops->get_size) |
377 | /* IFLA_INFO_DATA + nested data */ | 377 | /* IFLA_INFO_DATA + nested data */ |
378 | size += nla_total_size(sizeof(struct nlattr)) + | 378 | size += nla_total_size(sizeof(struct nlattr)) + |
379 | ops->get_size(dev); | 379 | ops->get_size(dev); |
380 | 380 | ||
381 | if (ops->get_xstats_size) | 381 | if (ops->get_xstats_size) |
382 | /* IFLA_INFO_XSTATS */ | 382 | /* IFLA_INFO_XSTATS */ |
383 | size += nla_total_size(ops->get_xstats_size(dev)); | 383 | size += nla_total_size(ops->get_xstats_size(dev)); |
384 | 384 | ||
385 | return size; | 385 | return size; |
386 | } | 386 | } |
387 | 387 | ||
388 | static LIST_HEAD(rtnl_af_ops); | 388 | static LIST_HEAD(rtnl_af_ops); |
389 | 389 | ||
390 | static const struct rtnl_af_ops *rtnl_af_lookup(const int family) | 390 | static const struct rtnl_af_ops *rtnl_af_lookup(const int family) |
391 | { | 391 | { |
392 | const struct rtnl_af_ops *ops; | 392 | const struct rtnl_af_ops *ops; |
393 | 393 | ||
394 | list_for_each_entry(ops, &rtnl_af_ops, list) { | 394 | list_for_each_entry(ops, &rtnl_af_ops, list) { |
395 | if (ops->family == family) | 395 | if (ops->family == family) |
396 | return ops; | 396 | return ops; |
397 | } | 397 | } |
398 | 398 | ||
399 | return NULL; | 399 | return NULL; |
400 | } | 400 | } |
401 | 401 | ||
402 | /** | 402 | /** |
403 | * __rtnl_af_register - Register rtnl_af_ops with rtnetlink. | 403 | * __rtnl_af_register - Register rtnl_af_ops with rtnetlink. |
404 | * @ops: struct rtnl_af_ops * to register | 404 | * @ops: struct rtnl_af_ops * to register |
405 | * | 405 | * |
406 | * The caller must hold the rtnl_mutex. | 406 | * The caller must hold the rtnl_mutex. |
407 | * | 407 | * |
408 | * Returns 0 on success or a negative error code. | 408 | * Returns 0 on success or a negative error code. |
409 | */ | 409 | */ |
410 | int __rtnl_af_register(struct rtnl_af_ops *ops) | 410 | int __rtnl_af_register(struct rtnl_af_ops *ops) |
411 | { | 411 | { |
412 | list_add_tail(&ops->list, &rtnl_af_ops); | 412 | list_add_tail(&ops->list, &rtnl_af_ops); |
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | EXPORT_SYMBOL_GPL(__rtnl_af_register); | 415 | EXPORT_SYMBOL_GPL(__rtnl_af_register); |
416 | 416 | ||
417 | /** | 417 | /** |
418 | * rtnl_af_register - Register rtnl_af_ops with rtnetlink. | 418 | * rtnl_af_register - Register rtnl_af_ops with rtnetlink. |
419 | * @ops: struct rtnl_af_ops * to register | 419 | * @ops: struct rtnl_af_ops * to register |
420 | * | 420 | * |
421 | * Returns 0 on success or a negative error code. | 421 | * Returns 0 on success or a negative error code. |
422 | */ | 422 | */ |
423 | int rtnl_af_register(struct rtnl_af_ops *ops) | 423 | int rtnl_af_register(struct rtnl_af_ops *ops) |
424 | { | 424 | { |
425 | int err; | 425 | int err; |
426 | 426 | ||
427 | rtnl_lock(); | 427 | rtnl_lock(); |
428 | err = __rtnl_af_register(ops); | 428 | err = __rtnl_af_register(ops); |
429 | rtnl_unlock(); | 429 | rtnl_unlock(); |
430 | return err; | 430 | return err; |
431 | } | 431 | } |
432 | EXPORT_SYMBOL_GPL(rtnl_af_register); | 432 | EXPORT_SYMBOL_GPL(rtnl_af_register); |
433 | 433 | ||
434 | /** | 434 | /** |
435 | * __rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. | 435 | * __rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. |
436 | * @ops: struct rtnl_af_ops * to unregister | 436 | * @ops: struct rtnl_af_ops * to unregister |
437 | * | 437 | * |
438 | * The caller must hold the rtnl_mutex. | 438 | * The caller must hold the rtnl_mutex. |
439 | */ | 439 | */ |
440 | void __rtnl_af_unregister(struct rtnl_af_ops *ops) | 440 | void __rtnl_af_unregister(struct rtnl_af_ops *ops) |
441 | { | 441 | { |
442 | list_del(&ops->list); | 442 | list_del(&ops->list); |
443 | } | 443 | } |
444 | EXPORT_SYMBOL_GPL(__rtnl_af_unregister); | 444 | EXPORT_SYMBOL_GPL(__rtnl_af_unregister); |
445 | 445 | ||
446 | /** | 446 | /** |
447 | * rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. | 447 | * rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. |
448 | * @ops: struct rtnl_af_ops * to unregister | 448 | * @ops: struct rtnl_af_ops * to unregister |
449 | */ | 449 | */ |
450 | void rtnl_af_unregister(struct rtnl_af_ops *ops) | 450 | void rtnl_af_unregister(struct rtnl_af_ops *ops) |
451 | { | 451 | { |
452 | rtnl_lock(); | 452 | rtnl_lock(); |
453 | __rtnl_af_unregister(ops); | 453 | __rtnl_af_unregister(ops); |
454 | rtnl_unlock(); | 454 | rtnl_unlock(); |
455 | } | 455 | } |
456 | EXPORT_SYMBOL_GPL(rtnl_af_unregister); | 456 | EXPORT_SYMBOL_GPL(rtnl_af_unregister); |
457 | 457 | ||
458 | static size_t rtnl_link_get_af_size(const struct net_device *dev) | 458 | static size_t rtnl_link_get_af_size(const struct net_device *dev) |
459 | { | 459 | { |
460 | struct rtnl_af_ops *af_ops; | 460 | struct rtnl_af_ops *af_ops; |
461 | size_t size; | 461 | size_t size; |
462 | 462 | ||
463 | /* IFLA_AF_SPEC */ | 463 | /* IFLA_AF_SPEC */ |
464 | size = nla_total_size(sizeof(struct nlattr)); | 464 | size = nla_total_size(sizeof(struct nlattr)); |
465 | 465 | ||
466 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { | 466 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { |
467 | if (af_ops->get_link_af_size) { | 467 | if (af_ops->get_link_af_size) { |
468 | /* AF_* + nested data */ | 468 | /* AF_* + nested data */ |
469 | size += nla_total_size(sizeof(struct nlattr)) + | 469 | size += nla_total_size(sizeof(struct nlattr)) + |
470 | af_ops->get_link_af_size(dev); | 470 | af_ops->get_link_af_size(dev); |
471 | } | 471 | } |
472 | } | 472 | } |
473 | 473 | ||
474 | return size; | 474 | return size; |
475 | } | 475 | } |
476 | 476 | ||
477 | static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) | 477 | static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) |
478 | { | 478 | { |
479 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | 479 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; |
480 | struct nlattr *linkinfo, *data; | 480 | struct nlattr *linkinfo, *data; |
481 | int err = -EMSGSIZE; | 481 | int err = -EMSGSIZE; |
482 | 482 | ||
483 | linkinfo = nla_nest_start(skb, IFLA_LINKINFO); | 483 | linkinfo = nla_nest_start(skb, IFLA_LINKINFO); |
484 | if (linkinfo == NULL) | 484 | if (linkinfo == NULL) |
485 | goto out; | 485 | goto out; |
486 | 486 | ||
487 | if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) | 487 | if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) |
488 | goto err_cancel_link; | 488 | goto err_cancel_link; |
489 | if (ops->fill_xstats) { | 489 | if (ops->fill_xstats) { |
490 | err = ops->fill_xstats(skb, dev); | 490 | err = ops->fill_xstats(skb, dev); |
491 | if (err < 0) | 491 | if (err < 0) |
492 | goto err_cancel_link; | 492 | goto err_cancel_link; |
493 | } | 493 | } |
494 | if (ops->fill_info) { | 494 | if (ops->fill_info) { |
495 | data = nla_nest_start(skb, IFLA_INFO_DATA); | 495 | data = nla_nest_start(skb, IFLA_INFO_DATA); |
496 | if (data == NULL) | 496 | if (data == NULL) |
497 | goto err_cancel_link; | 497 | goto err_cancel_link; |
498 | err = ops->fill_info(skb, dev); | 498 | err = ops->fill_info(skb, dev); |
499 | if (err < 0) | 499 | if (err < 0) |
500 | goto err_cancel_data; | 500 | goto err_cancel_data; |
501 | nla_nest_end(skb, data); | 501 | nla_nest_end(skb, data); |
502 | } | 502 | } |
503 | 503 | ||
504 | nla_nest_end(skb, linkinfo); | 504 | nla_nest_end(skb, linkinfo); |
505 | return 0; | 505 | return 0; |
506 | 506 | ||
507 | err_cancel_data: | 507 | err_cancel_data: |
508 | nla_nest_cancel(skb, data); | 508 | nla_nest_cancel(skb, data); |
509 | err_cancel_link: | 509 | err_cancel_link: |
510 | nla_nest_cancel(skb, linkinfo); | 510 | nla_nest_cancel(skb, linkinfo); |
511 | out: | 511 | out: |
512 | return err; | 512 | return err; |
513 | } | 513 | } |
514 | 514 | ||
515 | static const int rtm_min[RTM_NR_FAMILIES] = | 515 | static const int rtm_min[RTM_NR_FAMILIES] = |
516 | { | 516 | { |
517 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), | 517 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), |
518 | [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), | 518 | [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), |
519 | [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), | 519 | [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), |
520 | [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)), | 520 | [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)), |
521 | [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)), | 521 | [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
522 | [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), | 522 | [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
523 | [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), | 523 | [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
524 | [RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)), | 524 | [RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)), |
525 | [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), | 525 | [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), |
526 | [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), | 526 | [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), |
527 | }; | 527 | }; |
528 | 528 | ||
529 | static const int rta_max[RTM_NR_FAMILIES] = | 529 | static const int rta_max[RTM_NR_FAMILIES] = |
530 | { | 530 | { |
531 | [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX, | 531 | [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX, |
532 | [RTM_FAM(RTM_NEWADDR)] = IFA_MAX, | 532 | [RTM_FAM(RTM_NEWADDR)] = IFA_MAX, |
533 | [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX, | 533 | [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX, |
534 | [RTM_FAM(RTM_NEWRULE)] = FRA_MAX, | 534 | [RTM_FAM(RTM_NEWRULE)] = FRA_MAX, |
535 | [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX, | 535 | [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX, |
536 | [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, | 536 | [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, |
537 | [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, | 537 | [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, |
538 | [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, | 538 | [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, |
539 | }; | 539 | }; |
540 | 540 | ||
541 | void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) | 541 | void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) |
542 | { | 542 | { |
543 | struct rtattr *rta; | 543 | struct rtattr *rta; |
544 | int size = RTA_LENGTH(attrlen); | 544 | int size = RTA_LENGTH(attrlen); |
545 | 545 | ||
546 | rta = (struct rtattr *)skb_put(skb, RTA_ALIGN(size)); | 546 | rta = (struct rtattr *)skb_put(skb, RTA_ALIGN(size)); |
547 | rta->rta_type = attrtype; | 547 | rta->rta_type = attrtype; |
548 | rta->rta_len = size; | 548 | rta->rta_len = size; |
549 | memcpy(RTA_DATA(rta), data, attrlen); | 549 | memcpy(RTA_DATA(rta), data, attrlen); |
550 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); | 550 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); |
551 | } | 551 | } |
552 | EXPORT_SYMBOL(__rta_fill); | 552 | EXPORT_SYMBOL(__rta_fill); |
553 | 553 | ||
554 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) | 554 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) |
555 | { | 555 | { |
556 | struct sock *rtnl = net->rtnl; | 556 | struct sock *rtnl = net->rtnl; |
557 | int err = 0; | 557 | int err = 0; |
558 | 558 | ||
559 | NETLINK_CB(skb).dst_group = group; | 559 | NETLINK_CB(skb).dst_group = group; |
560 | if (echo) | 560 | if (echo) |
561 | atomic_inc(&skb->users); | 561 | atomic_inc(&skb->users); |
562 | netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL); | 562 | netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL); |
563 | if (echo) | 563 | if (echo) |
564 | err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); | 564 | err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); |
565 | return err; | 565 | return err; |
566 | } | 566 | } |
567 | 567 | ||
568 | int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) | 568 | int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) |
569 | { | 569 | { |
570 | struct sock *rtnl = net->rtnl; | 570 | struct sock *rtnl = net->rtnl; |
571 | 571 | ||
572 | return nlmsg_unicast(rtnl, skb, pid); | 572 | return nlmsg_unicast(rtnl, skb, pid); |
573 | } | 573 | } |
574 | EXPORT_SYMBOL(rtnl_unicast); | 574 | EXPORT_SYMBOL(rtnl_unicast); |
575 | 575 | ||
576 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | 576 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, |
577 | struct nlmsghdr *nlh, gfp_t flags) | 577 | struct nlmsghdr *nlh, gfp_t flags) |
578 | { | 578 | { |
579 | struct sock *rtnl = net->rtnl; | 579 | struct sock *rtnl = net->rtnl; |
580 | int report = 0; | 580 | int report = 0; |
581 | 581 | ||
582 | if (nlh) | 582 | if (nlh) |
583 | report = nlmsg_report(nlh); | 583 | report = nlmsg_report(nlh); |
584 | 584 | ||
585 | nlmsg_notify(rtnl, skb, pid, group, report, flags); | 585 | nlmsg_notify(rtnl, skb, pid, group, report, flags); |
586 | } | 586 | } |
587 | EXPORT_SYMBOL(rtnl_notify); | 587 | EXPORT_SYMBOL(rtnl_notify); |
588 | 588 | ||
589 | void rtnl_set_sk_err(struct net *net, u32 group, int error) | 589 | void rtnl_set_sk_err(struct net *net, u32 group, int error) |
590 | { | 590 | { |
591 | struct sock *rtnl = net->rtnl; | 591 | struct sock *rtnl = net->rtnl; |
592 | 592 | ||
593 | netlink_set_err(rtnl, 0, group, error); | 593 | netlink_set_err(rtnl, 0, group, error); |
594 | } | 594 | } |
595 | EXPORT_SYMBOL(rtnl_set_sk_err); | 595 | EXPORT_SYMBOL(rtnl_set_sk_err); |
596 | 596 | ||
597 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) | 597 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) |
598 | { | 598 | { |
599 | struct nlattr *mx; | 599 | struct nlattr *mx; |
600 | int i, valid = 0; | 600 | int i, valid = 0; |
601 | 601 | ||
602 | mx = nla_nest_start(skb, RTA_METRICS); | 602 | mx = nla_nest_start(skb, RTA_METRICS); |
603 | if (mx == NULL) | 603 | if (mx == NULL) |
604 | return -ENOBUFS; | 604 | return -ENOBUFS; |
605 | 605 | ||
606 | for (i = 0; i < RTAX_MAX; i++) { | 606 | for (i = 0; i < RTAX_MAX; i++) { |
607 | if (metrics[i]) { | 607 | if (metrics[i]) { |
608 | valid++; | 608 | valid++; |
609 | NLA_PUT_U32(skb, i+1, metrics[i]); | 609 | NLA_PUT_U32(skb, i+1, metrics[i]); |
610 | } | 610 | } |
611 | } | 611 | } |
612 | 612 | ||
613 | if (!valid) { | 613 | if (!valid) { |
614 | nla_nest_cancel(skb, mx); | 614 | nla_nest_cancel(skb, mx); |
615 | return 0; | 615 | return 0; |
616 | } | 616 | } |
617 | 617 | ||
618 | return nla_nest_end(skb, mx); | 618 | return nla_nest_end(skb, mx); |
619 | 619 | ||
620 | nla_put_failure: | 620 | nla_put_failure: |
621 | nla_nest_cancel(skb, mx); | 621 | nla_nest_cancel(skb, mx); |
622 | return -EMSGSIZE; | 622 | return -EMSGSIZE; |
623 | } | 623 | } |
624 | EXPORT_SYMBOL(rtnetlink_put_metrics); | 624 | EXPORT_SYMBOL(rtnetlink_put_metrics); |
625 | 625 | ||
626 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | 626 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, |
627 | u32 ts, u32 tsage, long expires, u32 error) | 627 | u32 ts, u32 tsage, long expires, u32 error) |
628 | { | 628 | { |
629 | struct rta_cacheinfo ci = { | 629 | struct rta_cacheinfo ci = { |
630 | .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), | 630 | .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), |
631 | .rta_used = dst->__use, | 631 | .rta_used = dst->__use, |
632 | .rta_clntref = atomic_read(&(dst->__refcnt)), | 632 | .rta_clntref = atomic_read(&(dst->__refcnt)), |
633 | .rta_error = error, | 633 | .rta_error = error, |
634 | .rta_id = id, | 634 | .rta_id = id, |
635 | .rta_ts = ts, | 635 | .rta_ts = ts, |
636 | .rta_tsage = tsage, | 636 | .rta_tsage = tsage, |
637 | }; | 637 | }; |
638 | 638 | ||
639 | if (expires) | 639 | if (expires) |
640 | ci.rta_expires = jiffies_to_clock_t(expires); | 640 | ci.rta_expires = jiffies_to_clock_t(expires); |
641 | 641 | ||
642 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); | 642 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); |
643 | } | 643 | } |
644 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); | 644 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); |
645 | 645 | ||
646 | static void set_operstate(struct net_device *dev, unsigned char transition) | 646 | static void set_operstate(struct net_device *dev, unsigned char transition) |
647 | { | 647 | { |
648 | unsigned char operstate = dev->operstate; | 648 | unsigned char operstate = dev->operstate; |
649 | 649 | ||
650 | switch (transition) { | 650 | switch (transition) { |
651 | case IF_OPER_UP: | 651 | case IF_OPER_UP: |
652 | if ((operstate == IF_OPER_DORMANT || | 652 | if ((operstate == IF_OPER_DORMANT || |
653 | operstate == IF_OPER_UNKNOWN) && | 653 | operstate == IF_OPER_UNKNOWN) && |
654 | !netif_dormant(dev)) | 654 | !netif_dormant(dev)) |
655 | operstate = IF_OPER_UP; | 655 | operstate = IF_OPER_UP; |
656 | break; | 656 | break; |
657 | 657 | ||
658 | case IF_OPER_DORMANT: | 658 | case IF_OPER_DORMANT: |
659 | if (operstate == IF_OPER_UP || | 659 | if (operstate == IF_OPER_UP || |
660 | operstate == IF_OPER_UNKNOWN) | 660 | operstate == IF_OPER_UNKNOWN) |
661 | operstate = IF_OPER_DORMANT; | 661 | operstate = IF_OPER_DORMANT; |
662 | break; | 662 | break; |
663 | } | 663 | } |
664 | 664 | ||
665 | if (dev->operstate != operstate) { | 665 | if (dev->operstate != operstate) { |
666 | write_lock_bh(&dev_base_lock); | 666 | write_lock_bh(&dev_base_lock); |
667 | dev->operstate = operstate; | 667 | dev->operstate = operstate; |
668 | write_unlock_bh(&dev_base_lock); | 668 | write_unlock_bh(&dev_base_lock); |
669 | netdev_state_change(dev); | 669 | netdev_state_change(dev); |
670 | } | 670 | } |
671 | } | 671 | } |
672 | 672 | ||
673 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | 673 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, |
674 | const struct ifinfomsg *ifm) | 674 | const struct ifinfomsg *ifm) |
675 | { | 675 | { |
676 | unsigned int flags = ifm->ifi_flags; | 676 | unsigned int flags = ifm->ifi_flags; |
677 | 677 | ||
678 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ | 678 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ |
679 | if (ifm->ifi_change) | 679 | if (ifm->ifi_change) |
680 | flags = (flags & ifm->ifi_change) | | 680 | flags = (flags & ifm->ifi_change) | |
681 | (dev->flags & ~ifm->ifi_change); | 681 | (dev->flags & ~ifm->ifi_change); |
682 | 682 | ||
683 | return flags; | 683 | return flags; |
684 | } | 684 | } |
685 | 685 | ||
686 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | 686 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, |
687 | const struct rtnl_link_stats64 *b) | 687 | const struct rtnl_link_stats64 *b) |
688 | { | 688 | { |
689 | a->rx_packets = b->rx_packets; | 689 | a->rx_packets = b->rx_packets; |
690 | a->tx_packets = b->tx_packets; | 690 | a->tx_packets = b->tx_packets; |
691 | a->rx_bytes = b->rx_bytes; | 691 | a->rx_bytes = b->rx_bytes; |
692 | a->tx_bytes = b->tx_bytes; | 692 | a->tx_bytes = b->tx_bytes; |
693 | a->rx_errors = b->rx_errors; | 693 | a->rx_errors = b->rx_errors; |
694 | a->tx_errors = b->tx_errors; | 694 | a->tx_errors = b->tx_errors; |
695 | a->rx_dropped = b->rx_dropped; | 695 | a->rx_dropped = b->rx_dropped; |
696 | a->tx_dropped = b->tx_dropped; | 696 | a->tx_dropped = b->tx_dropped; |
697 | 697 | ||
698 | a->multicast = b->multicast; | 698 | a->multicast = b->multicast; |
699 | a->collisions = b->collisions; | 699 | a->collisions = b->collisions; |
700 | 700 | ||
701 | a->rx_length_errors = b->rx_length_errors; | 701 | a->rx_length_errors = b->rx_length_errors; |
702 | a->rx_over_errors = b->rx_over_errors; | 702 | a->rx_over_errors = b->rx_over_errors; |
703 | a->rx_crc_errors = b->rx_crc_errors; | 703 | a->rx_crc_errors = b->rx_crc_errors; |
704 | a->rx_frame_errors = b->rx_frame_errors; | 704 | a->rx_frame_errors = b->rx_frame_errors; |
705 | a->rx_fifo_errors = b->rx_fifo_errors; | 705 | a->rx_fifo_errors = b->rx_fifo_errors; |
706 | a->rx_missed_errors = b->rx_missed_errors; | 706 | a->rx_missed_errors = b->rx_missed_errors; |
707 | 707 | ||
708 | a->tx_aborted_errors = b->tx_aborted_errors; | 708 | a->tx_aborted_errors = b->tx_aborted_errors; |
709 | a->tx_carrier_errors = b->tx_carrier_errors; | 709 | a->tx_carrier_errors = b->tx_carrier_errors; |
710 | a->tx_fifo_errors = b->tx_fifo_errors; | 710 | a->tx_fifo_errors = b->tx_fifo_errors; |
711 | a->tx_heartbeat_errors = b->tx_heartbeat_errors; | 711 | a->tx_heartbeat_errors = b->tx_heartbeat_errors; |
712 | a->tx_window_errors = b->tx_window_errors; | 712 | a->tx_window_errors = b->tx_window_errors; |
713 | 713 | ||
714 | a->rx_compressed = b->rx_compressed; | 714 | a->rx_compressed = b->rx_compressed; |
715 | a->tx_compressed = b->tx_compressed; | 715 | a->tx_compressed = b->tx_compressed; |
716 | } | 716 | } |
717 | 717 | ||
718 | static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) | 718 | static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) |
719 | { | 719 | { |
720 | memcpy(v, b, sizeof(*b)); | 720 | memcpy(v, b, sizeof(*b)); |
721 | } | 721 | } |
722 | 722 | ||
723 | /* All VF info */ | 723 | /* All VF info */ |
724 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | 724 | static inline int rtnl_vfinfo_size(const struct net_device *dev) |
725 | { | 725 | { |
726 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { | 726 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { |
727 | 727 | ||
728 | int num_vfs = dev_num_vf(dev->dev.parent); | 728 | int num_vfs = dev_num_vf(dev->dev.parent); |
729 | size_t size = nla_total_size(sizeof(struct nlattr)); | 729 | size_t size = nla_total_size(sizeof(struct nlattr)); |
730 | size += nla_total_size(num_vfs * sizeof(struct nlattr)); | 730 | size += nla_total_size(num_vfs * sizeof(struct nlattr)); |
731 | size += num_vfs * | 731 | size += num_vfs * |
732 | (nla_total_size(sizeof(struct ifla_vf_mac)) + | 732 | (nla_total_size(sizeof(struct ifla_vf_mac)) + |
733 | nla_total_size(sizeof(struct ifla_vf_vlan)) + | 733 | nla_total_size(sizeof(struct ifla_vf_vlan)) + |
734 | nla_total_size(sizeof(struct ifla_vf_tx_rate))); | 734 | nla_total_size(sizeof(struct ifla_vf_tx_rate))); |
735 | return size; | 735 | return size; |
736 | } else | 736 | } else |
737 | return 0; | 737 | return 0; |
738 | } | 738 | } |
739 | 739 | ||
740 | static size_t rtnl_port_size(const struct net_device *dev) | 740 | static size_t rtnl_port_size(const struct net_device *dev) |
741 | { | 741 | { |
742 | size_t port_size = nla_total_size(4) /* PORT_VF */ | 742 | size_t port_size = nla_total_size(4) /* PORT_VF */ |
743 | + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ | 743 | + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ |
744 | + nla_total_size(sizeof(struct ifla_port_vsi)) | 744 | + nla_total_size(sizeof(struct ifla_port_vsi)) |
745 | /* PORT_VSI_TYPE */ | 745 | /* PORT_VSI_TYPE */ |
746 | + nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */ | 746 | + nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */ |
747 | + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */ | 747 | + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */ |
748 | + nla_total_size(1) /* PROT_VDP_REQUEST */ | 748 | + nla_total_size(1) /* PROT_VDP_REQUEST */ |
749 | + nla_total_size(2); /* PORT_VDP_RESPONSE */ | 749 | + nla_total_size(2); /* PORT_VDP_RESPONSE */ |
750 | size_t vf_ports_size = nla_total_size(sizeof(struct nlattr)); | 750 | size_t vf_ports_size = nla_total_size(sizeof(struct nlattr)); |
751 | size_t vf_port_size = nla_total_size(sizeof(struct nlattr)) | 751 | size_t vf_port_size = nla_total_size(sizeof(struct nlattr)) |
752 | + port_size; | 752 | + port_size; |
753 | size_t port_self_size = nla_total_size(sizeof(struct nlattr)) | 753 | size_t port_self_size = nla_total_size(sizeof(struct nlattr)) |
754 | + port_size; | 754 | + port_size; |
755 | 755 | ||
756 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | 756 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) |
757 | return 0; | 757 | return 0; |
758 | if (dev_num_vf(dev->dev.parent)) | 758 | if (dev_num_vf(dev->dev.parent)) |
759 | return port_self_size + vf_ports_size + | 759 | return port_self_size + vf_ports_size + |
760 | vf_port_size * dev_num_vf(dev->dev.parent); | 760 | vf_port_size * dev_num_vf(dev->dev.parent); |
761 | else | 761 | else |
762 | return port_self_size; | 762 | return port_self_size; |
763 | } | 763 | } |
764 | 764 | ||
765 | static noinline size_t if_nlmsg_size(const struct net_device *dev) | 765 | static noinline size_t if_nlmsg_size(const struct net_device *dev) |
766 | { | 766 | { |
767 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 767 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
768 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 768 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
769 | + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ | 769 | + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ |
770 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ | 770 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
771 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) | 771 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) |
772 | + nla_total_size(sizeof(struct rtnl_link_stats)) | 772 | + nla_total_size(sizeof(struct rtnl_link_stats)) |
773 | + nla_total_size(sizeof(struct rtnl_link_stats64)) | 773 | + nla_total_size(sizeof(struct rtnl_link_stats64)) |
774 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | 774 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ |
775 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ | 775 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ |
776 | + nla_total_size(4) /* IFLA_TXQLEN */ | 776 | + nla_total_size(4) /* IFLA_TXQLEN */ |
777 | + nla_total_size(4) /* IFLA_WEIGHT */ | 777 | + nla_total_size(4) /* IFLA_WEIGHT */ |
778 | + nla_total_size(4) /* IFLA_MTU */ | 778 | + nla_total_size(4) /* IFLA_MTU */ |
779 | + nla_total_size(4) /* IFLA_LINK */ | 779 | + nla_total_size(4) /* IFLA_LINK */ |
780 | + nla_total_size(4) /* IFLA_MASTER */ | 780 | + nla_total_size(4) /* IFLA_MASTER */ |
781 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 781 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
782 | + nla_total_size(1) /* IFLA_LINKMODE */ | 782 | + nla_total_size(1) /* IFLA_LINKMODE */ |
783 | + nla_total_size(4) /* IFLA_NUM_VF */ | 783 | + nla_total_size(4) /* IFLA_NUM_VF */ |
784 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ | 784 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ |
785 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ | 785 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ |
786 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ | 786 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ |
787 | + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */ | 787 | + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */ |
788 | } | 788 | } |
789 | 789 | ||
790 | static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) | 790 | static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) |
791 | { | 791 | { |
792 | struct nlattr *vf_ports; | 792 | struct nlattr *vf_ports; |
793 | struct nlattr *vf_port; | 793 | struct nlattr *vf_port; |
794 | int vf; | 794 | int vf; |
795 | int err; | 795 | int err; |
796 | 796 | ||
797 | vf_ports = nla_nest_start(skb, IFLA_VF_PORTS); | 797 | vf_ports = nla_nest_start(skb, IFLA_VF_PORTS); |
798 | if (!vf_ports) | 798 | if (!vf_ports) |
799 | return -EMSGSIZE; | 799 | return -EMSGSIZE; |
800 | 800 | ||
801 | for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { | 801 | for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { |
802 | vf_port = nla_nest_start(skb, IFLA_VF_PORT); | 802 | vf_port = nla_nest_start(skb, IFLA_VF_PORT); |
803 | if (!vf_port) | 803 | if (!vf_port) |
804 | goto nla_put_failure; | 804 | goto nla_put_failure; |
805 | NLA_PUT_U32(skb, IFLA_PORT_VF, vf); | 805 | NLA_PUT_U32(skb, IFLA_PORT_VF, vf); |
806 | err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); | 806 | err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); |
807 | if (err == -EMSGSIZE) | 807 | if (err == -EMSGSIZE) |
808 | goto nla_put_failure; | 808 | goto nla_put_failure; |
809 | if (err) { | 809 | if (err) { |
810 | nla_nest_cancel(skb, vf_port); | 810 | nla_nest_cancel(skb, vf_port); |
811 | continue; | 811 | continue; |
812 | } | 812 | } |
813 | nla_nest_end(skb, vf_port); | 813 | nla_nest_end(skb, vf_port); |
814 | } | 814 | } |
815 | 815 | ||
816 | nla_nest_end(skb, vf_ports); | 816 | nla_nest_end(skb, vf_ports); |
817 | 817 | ||
818 | return 0; | 818 | return 0; |
819 | 819 | ||
820 | nla_put_failure: | 820 | nla_put_failure: |
821 | nla_nest_cancel(skb, vf_ports); | 821 | nla_nest_cancel(skb, vf_ports); |
822 | return -EMSGSIZE; | 822 | return -EMSGSIZE; |
823 | } | 823 | } |
824 | 824 | ||
825 | static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) | 825 | static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) |
826 | { | 826 | { |
827 | struct nlattr *port_self; | 827 | struct nlattr *port_self; |
828 | int err; | 828 | int err; |
829 | 829 | ||
830 | port_self = nla_nest_start(skb, IFLA_PORT_SELF); | 830 | port_self = nla_nest_start(skb, IFLA_PORT_SELF); |
831 | if (!port_self) | 831 | if (!port_self) |
832 | return -EMSGSIZE; | 832 | return -EMSGSIZE; |
833 | 833 | ||
834 | err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); | 834 | err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); |
835 | if (err) { | 835 | if (err) { |
836 | nla_nest_cancel(skb, port_self); | 836 | nla_nest_cancel(skb, port_self); |
837 | return (err == -EMSGSIZE) ? err : 0; | 837 | return (err == -EMSGSIZE) ? err : 0; |
838 | } | 838 | } |
839 | 839 | ||
840 | nla_nest_end(skb, port_self); | 840 | nla_nest_end(skb, port_self); |
841 | 841 | ||
842 | return 0; | 842 | return 0; |
843 | } | 843 | } |
844 | 844 | ||
845 | static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) | 845 | static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) |
846 | { | 846 | { |
847 | int err; | 847 | int err; |
848 | 848 | ||
849 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | 849 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) |
850 | return 0; | 850 | return 0; |
851 | 851 | ||
852 | err = rtnl_port_self_fill(skb, dev); | 852 | err = rtnl_port_self_fill(skb, dev); |
853 | if (err) | 853 | if (err) |
854 | return err; | 854 | return err; |
855 | 855 | ||
856 | if (dev_num_vf(dev->dev.parent)) { | 856 | if (dev_num_vf(dev->dev.parent)) { |
857 | err = rtnl_vf_ports_fill(skb, dev); | 857 | err = rtnl_vf_ports_fill(skb, dev); |
858 | if (err) | 858 | if (err) |
859 | return err; | 859 | return err; |
860 | } | 860 | } |
861 | 861 | ||
862 | return 0; | 862 | return 0; |
863 | } | 863 | } |
864 | 864 | ||
865 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 865 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
866 | int type, u32 pid, u32 seq, u32 change, | 866 | int type, u32 pid, u32 seq, u32 change, |
867 | unsigned int flags) | 867 | unsigned int flags) |
868 | { | 868 | { |
869 | struct ifinfomsg *ifm; | 869 | struct ifinfomsg *ifm; |
870 | struct nlmsghdr *nlh; | 870 | struct nlmsghdr *nlh; |
871 | struct rtnl_link_stats64 temp; | 871 | struct rtnl_link_stats64 temp; |
872 | const struct rtnl_link_stats64 *stats; | 872 | const struct rtnl_link_stats64 *stats; |
873 | struct nlattr *attr, *af_spec; | 873 | struct nlattr *attr, *af_spec; |
874 | struct rtnl_af_ops *af_ops; | 874 | struct rtnl_af_ops *af_ops; |
875 | 875 | ||
876 | ASSERT_RTNL(); | 876 | ASSERT_RTNL(); |
877 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); | 877 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); |
878 | if (nlh == NULL) | 878 | if (nlh == NULL) |
879 | return -EMSGSIZE; | 879 | return -EMSGSIZE; |
880 | 880 | ||
881 | ifm = nlmsg_data(nlh); | 881 | ifm = nlmsg_data(nlh); |
882 | ifm->ifi_family = AF_UNSPEC; | 882 | ifm->ifi_family = AF_UNSPEC; |
883 | ifm->__ifi_pad = 0; | 883 | ifm->__ifi_pad = 0; |
884 | ifm->ifi_type = dev->type; | 884 | ifm->ifi_type = dev->type; |
885 | ifm->ifi_index = dev->ifindex; | 885 | ifm->ifi_index = dev->ifindex; |
886 | ifm->ifi_flags = dev_get_flags(dev); | 886 | ifm->ifi_flags = dev_get_flags(dev); |
887 | ifm->ifi_change = change; | 887 | ifm->ifi_change = change; |
888 | 888 | ||
889 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); | 889 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); |
890 | NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); | 890 | NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); |
891 | NLA_PUT_U8(skb, IFLA_OPERSTATE, | 891 | NLA_PUT_U8(skb, IFLA_OPERSTATE, |
892 | netif_running(dev) ? dev->operstate : IF_OPER_DOWN); | 892 | netif_running(dev) ? dev->operstate : IF_OPER_DOWN); |
893 | NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); | 893 | NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); |
894 | NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); | 894 | NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); |
895 | NLA_PUT_U32(skb, IFLA_GROUP, dev->group); | 895 | NLA_PUT_U32(skb, IFLA_GROUP, dev->group); |
896 | 896 | ||
897 | if (dev->ifindex != dev->iflink) | 897 | if (dev->ifindex != dev->iflink) |
898 | NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); | 898 | NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); |
899 | 899 | ||
900 | if (dev->master) | 900 | if (dev->master) |
901 | NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); | 901 | NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); |
902 | 902 | ||
903 | if (dev->qdisc) | 903 | if (dev->qdisc) |
904 | NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc->ops->id); | 904 | NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc->ops->id); |
905 | 905 | ||
906 | if (dev->ifalias) | 906 | if (dev->ifalias) |
907 | NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); | 907 | NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); |
908 | 908 | ||
909 | if (1) { | 909 | if (1) { |
910 | struct rtnl_link_ifmap map = { | 910 | struct rtnl_link_ifmap map = { |
911 | .mem_start = dev->mem_start, | 911 | .mem_start = dev->mem_start, |
912 | .mem_end = dev->mem_end, | 912 | .mem_end = dev->mem_end, |
913 | .base_addr = dev->base_addr, | 913 | .base_addr = dev->base_addr, |
914 | .irq = dev->irq, | 914 | .irq = dev->irq, |
915 | .dma = dev->dma, | 915 | .dma = dev->dma, |
916 | .port = dev->if_port, | 916 | .port = dev->if_port, |
917 | }; | 917 | }; |
918 | NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); | 918 | NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); |
919 | } | 919 | } |
920 | 920 | ||
921 | if (dev->addr_len) { | 921 | if (dev->addr_len) { |
922 | NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); | 922 | NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); |
923 | NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); | 923 | NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); |
924 | } | 924 | } |
925 | 925 | ||
926 | attr = nla_reserve(skb, IFLA_STATS, | 926 | attr = nla_reserve(skb, IFLA_STATS, |
927 | sizeof(struct rtnl_link_stats)); | 927 | sizeof(struct rtnl_link_stats)); |
928 | if (attr == NULL) | 928 | if (attr == NULL) |
929 | goto nla_put_failure; | 929 | goto nla_put_failure; |
930 | 930 | ||
931 | stats = dev_get_stats(dev, &temp); | 931 | stats = dev_get_stats(dev, &temp); |
932 | copy_rtnl_link_stats(nla_data(attr), stats); | 932 | copy_rtnl_link_stats(nla_data(attr), stats); |
933 | 933 | ||
934 | attr = nla_reserve(skb, IFLA_STATS64, | 934 | attr = nla_reserve(skb, IFLA_STATS64, |
935 | sizeof(struct rtnl_link_stats64)); | 935 | sizeof(struct rtnl_link_stats64)); |
936 | if (attr == NULL) | 936 | if (attr == NULL) |
937 | goto nla_put_failure; | 937 | goto nla_put_failure; |
938 | copy_rtnl_link_stats64(nla_data(attr), stats); | 938 | copy_rtnl_link_stats64(nla_data(attr), stats); |
939 | 939 | ||
940 | if (dev->dev.parent) | 940 | if (dev->dev.parent) |
941 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | 941 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); |
942 | 942 | ||
943 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | 943 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { |
944 | int i; | 944 | int i; |
945 | 945 | ||
946 | struct nlattr *vfinfo, *vf; | 946 | struct nlattr *vfinfo, *vf; |
947 | int num_vfs = dev_num_vf(dev->dev.parent); | 947 | int num_vfs = dev_num_vf(dev->dev.parent); |
948 | 948 | ||
949 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); | 949 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); |
950 | if (!vfinfo) | 950 | if (!vfinfo) |
951 | goto nla_put_failure; | 951 | goto nla_put_failure; |
952 | for (i = 0; i < num_vfs; i++) { | 952 | for (i = 0; i < num_vfs; i++) { |
953 | struct ifla_vf_info ivi; | 953 | struct ifla_vf_info ivi; |
954 | struct ifla_vf_mac vf_mac; | 954 | struct ifla_vf_mac vf_mac; |
955 | struct ifla_vf_vlan vf_vlan; | 955 | struct ifla_vf_vlan vf_vlan; |
956 | struct ifla_vf_tx_rate vf_tx_rate; | 956 | struct ifla_vf_tx_rate vf_tx_rate; |
957 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | 957 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) |
958 | break; | 958 | break; |
959 | vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; | 959 | vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; |
960 | memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); | 960 | memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); |
961 | vf_vlan.vlan = ivi.vlan; | 961 | vf_vlan.vlan = ivi.vlan; |
962 | vf_vlan.qos = ivi.qos; | 962 | vf_vlan.qos = ivi.qos; |
963 | vf_tx_rate.rate = ivi.tx_rate; | 963 | vf_tx_rate.rate = ivi.tx_rate; |
964 | vf = nla_nest_start(skb, IFLA_VF_INFO); | 964 | vf = nla_nest_start(skb, IFLA_VF_INFO); |
965 | if (!vf) { | 965 | if (!vf) { |
966 | nla_nest_cancel(skb, vfinfo); | 966 | nla_nest_cancel(skb, vfinfo); |
967 | goto nla_put_failure; | 967 | goto nla_put_failure; |
968 | } | 968 | } |
969 | NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); | 969 | NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); |
970 | NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); | 970 | NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); |
971 | NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); | 971 | NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); |
972 | nla_nest_end(skb, vf); | 972 | nla_nest_end(skb, vf); |
973 | } | 973 | } |
974 | nla_nest_end(skb, vfinfo); | 974 | nla_nest_end(skb, vfinfo); |
975 | } | 975 | } |
976 | 976 | ||
977 | if (rtnl_port_fill(skb, dev)) | 977 | if (rtnl_port_fill(skb, dev)) |
978 | goto nla_put_failure; | 978 | goto nla_put_failure; |
979 | 979 | ||
980 | if (dev->rtnl_link_ops) { | 980 | if (dev->rtnl_link_ops) { |
981 | if (rtnl_link_fill(skb, dev) < 0) | 981 | if (rtnl_link_fill(skb, dev) < 0) |
982 | goto nla_put_failure; | 982 | goto nla_put_failure; |
983 | } | 983 | } |
984 | 984 | ||
985 | if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC))) | 985 | if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC))) |
986 | goto nla_put_failure; | 986 | goto nla_put_failure; |
987 | 987 | ||
988 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { | 988 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { |
989 | if (af_ops->fill_link_af) { | 989 | if (af_ops->fill_link_af) { |
990 | struct nlattr *af; | 990 | struct nlattr *af; |
991 | int err; | 991 | int err; |
992 | 992 | ||
993 | if (!(af = nla_nest_start(skb, af_ops->family))) | 993 | if (!(af = nla_nest_start(skb, af_ops->family))) |
994 | goto nla_put_failure; | 994 | goto nla_put_failure; |
995 | 995 | ||
996 | err = af_ops->fill_link_af(skb, dev); | 996 | err = af_ops->fill_link_af(skb, dev); |
997 | 997 | ||
998 | /* | 998 | /* |
999 | * Caller may return ENODATA to indicate that there | 999 | * Caller may return ENODATA to indicate that there |
1000 | * was no data to be dumped. This is not an error, it | 1000 | * was no data to be dumped. This is not an error, it |
1001 | * means we should trim the attribute header and | 1001 | * means we should trim the attribute header and |
1002 | * continue. | 1002 | * continue. |
1003 | */ | 1003 | */ |
1004 | if (err == -ENODATA) | 1004 | if (err == -ENODATA) |
1005 | nla_nest_cancel(skb, af); | 1005 | nla_nest_cancel(skb, af); |
1006 | else if (err < 0) | 1006 | else if (err < 0) |
1007 | goto nla_put_failure; | 1007 | goto nla_put_failure; |
1008 | 1008 | ||
1009 | nla_nest_end(skb, af); | 1009 | nla_nest_end(skb, af); |
1010 | } | 1010 | } |
1011 | } | 1011 | } |
1012 | 1012 | ||
1013 | nla_nest_end(skb, af_spec); | 1013 | nla_nest_end(skb, af_spec); |
1014 | 1014 | ||
1015 | return nlmsg_end(skb, nlh); | 1015 | return nlmsg_end(skb, nlh); |
1016 | 1016 | ||
1017 | nla_put_failure: | 1017 | nla_put_failure: |
1018 | nlmsg_cancel(skb, nlh); | 1018 | nlmsg_cancel(skb, nlh); |
1019 | return -EMSGSIZE; | 1019 | return -EMSGSIZE; |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 1022 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
1023 | { | 1023 | { |
1024 | struct net *net = sock_net(skb->sk); | 1024 | struct net *net = sock_net(skb->sk); |
1025 | int h, s_h; | 1025 | int h, s_h; |
1026 | int idx = 0, s_idx; | 1026 | int idx = 0, s_idx; |
1027 | struct net_device *dev; | 1027 | struct net_device *dev; |
1028 | struct hlist_head *head; | 1028 | struct hlist_head *head; |
1029 | struct hlist_node *node; | 1029 | struct hlist_node *node; |
1030 | 1030 | ||
1031 | s_h = cb->args[0]; | 1031 | s_h = cb->args[0]; |
1032 | s_idx = cb->args[1]; | 1032 | s_idx = cb->args[1]; |
1033 | 1033 | ||
1034 | rcu_read_lock(); | 1034 | rcu_read_lock(); |
1035 | cb->seq = net->dev_base_seq; | 1035 | cb->seq = net->dev_base_seq; |
1036 | 1036 | ||
1037 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | 1037 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
1038 | idx = 0; | 1038 | idx = 0; |
1039 | head = &net->dev_index_head[h]; | 1039 | head = &net->dev_index_head[h]; |
1040 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { | 1040 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
1041 | if (idx < s_idx) | 1041 | if (idx < s_idx) |
1042 | goto cont; | 1042 | goto cont; |
1043 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | 1043 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, |
1044 | NETLINK_CB(cb->skb).pid, | 1044 | NETLINK_CB(cb->skb).pid, |
1045 | cb->nlh->nlmsg_seq, 0, | 1045 | cb->nlh->nlmsg_seq, 0, |
1046 | NLM_F_MULTI) <= 0) | 1046 | NLM_F_MULTI) <= 0) |
1047 | goto out; | 1047 | goto out; |
1048 | 1048 | ||
1049 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 1049 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
1050 | cont: | 1050 | cont: |
1051 | idx++; | 1051 | idx++; |
1052 | } | 1052 | } |
1053 | } | 1053 | } |
1054 | out: | 1054 | out: |
1055 | rcu_read_unlock(); | 1055 | rcu_read_unlock(); |
1056 | cb->args[1] = idx; | 1056 | cb->args[1] = idx; |
1057 | cb->args[0] = h; | 1057 | cb->args[0] = h; |
1058 | 1058 | ||
1059 | return skb->len; | 1059 | return skb->len; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | const struct nla_policy ifla_policy[IFLA_MAX+1] = { | 1062 | const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
1063 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 1063 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
1064 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1064 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
1065 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1065 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
1066 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, | 1066 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, |
1067 | [IFLA_MTU] = { .type = NLA_U32 }, | 1067 | [IFLA_MTU] = { .type = NLA_U32 }, |
1068 | [IFLA_LINK] = { .type = NLA_U32 }, | 1068 | [IFLA_LINK] = { .type = NLA_U32 }, |
1069 | [IFLA_MASTER] = { .type = NLA_U32 }, | 1069 | [IFLA_MASTER] = { .type = NLA_U32 }, |
1070 | [IFLA_TXQLEN] = { .type = NLA_U32 }, | 1070 | [IFLA_TXQLEN] = { .type = NLA_U32 }, |
1071 | [IFLA_WEIGHT] = { .type = NLA_U32 }, | 1071 | [IFLA_WEIGHT] = { .type = NLA_U32 }, |
1072 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, | 1072 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, |
1073 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 1073 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
1074 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 1074 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
1075 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 1075 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
1076 | [IFLA_NET_NS_FD] = { .type = NLA_U32 }, | 1076 | [IFLA_NET_NS_FD] = { .type = NLA_U32 }, |
1077 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 1077 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
1078 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, | 1078 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, |
1079 | [IFLA_VF_PORTS] = { .type = NLA_NESTED }, | 1079 | [IFLA_VF_PORTS] = { .type = NLA_NESTED }, |
1080 | [IFLA_PORT_SELF] = { .type = NLA_NESTED }, | 1080 | [IFLA_PORT_SELF] = { .type = NLA_NESTED }, |
1081 | [IFLA_AF_SPEC] = { .type = NLA_NESTED }, | 1081 | [IFLA_AF_SPEC] = { .type = NLA_NESTED }, |
1082 | }; | 1082 | }; |
1083 | EXPORT_SYMBOL(ifla_policy); | 1083 | EXPORT_SYMBOL(ifla_policy); |
1084 | 1084 | ||
1085 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 1085 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
1086 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, | 1086 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
1087 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 1087 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
1088 | }; | 1088 | }; |
1089 | 1089 | ||
1090 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | 1090 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { |
1091 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, | 1091 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, |
1092 | }; | 1092 | }; |
1093 | 1093 | ||
1094 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | 1094 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { |
1095 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | 1095 | [IFLA_VF_MAC] = { .type = NLA_BINARY, |
1096 | .len = sizeof(struct ifla_vf_mac) }, | 1096 | .len = sizeof(struct ifla_vf_mac) }, |
1097 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | 1097 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, |
1098 | .len = sizeof(struct ifla_vf_vlan) }, | 1098 | .len = sizeof(struct ifla_vf_vlan) }, |
1099 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | 1099 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, |
1100 | .len = sizeof(struct ifla_vf_tx_rate) }, | 1100 | .len = sizeof(struct ifla_vf_tx_rate) }, |
1101 | }; | 1101 | }; |
1102 | 1102 | ||
1103 | static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { | 1103 | static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { |
1104 | [IFLA_PORT_VF] = { .type = NLA_U32 }, | 1104 | [IFLA_PORT_VF] = { .type = NLA_U32 }, |
1105 | [IFLA_PORT_PROFILE] = { .type = NLA_STRING, | 1105 | [IFLA_PORT_PROFILE] = { .type = NLA_STRING, |
1106 | .len = PORT_PROFILE_MAX }, | 1106 | .len = PORT_PROFILE_MAX }, |
1107 | [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY, | 1107 | [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY, |
1108 | .len = sizeof(struct ifla_port_vsi)}, | 1108 | .len = sizeof(struct ifla_port_vsi)}, |
1109 | [IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY, | 1109 | [IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY, |
1110 | .len = PORT_UUID_MAX }, | 1110 | .len = PORT_UUID_MAX }, |
1111 | [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING, | 1111 | [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING, |
1112 | .len = PORT_UUID_MAX }, | 1112 | .len = PORT_UUID_MAX }, |
1113 | [IFLA_PORT_REQUEST] = { .type = NLA_U8, }, | 1113 | [IFLA_PORT_REQUEST] = { .type = NLA_U8, }, |
1114 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, | 1114 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, |
1115 | }; | 1115 | }; |
1116 | 1116 | ||
1117 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 1117 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
1118 | { | 1118 | { |
1119 | struct net *net; | 1119 | struct net *net; |
1120 | /* Examine the link attributes and figure out which | 1120 | /* Examine the link attributes and figure out which |
1121 | * network namespace we are talking about. | 1121 | * network namespace we are talking about. |
1122 | */ | 1122 | */ |
1123 | if (tb[IFLA_NET_NS_PID]) | 1123 | if (tb[IFLA_NET_NS_PID]) |
1124 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | 1124 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); |
1125 | else if (tb[IFLA_NET_NS_FD]) | 1125 | else if (tb[IFLA_NET_NS_FD]) |
1126 | net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD])); | 1126 | net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD])); |
1127 | else | 1127 | else |
1128 | net = get_net(src_net); | 1128 | net = get_net(src_net); |
1129 | return net; | 1129 | return net; |
1130 | } | 1130 | } |
1131 | EXPORT_SYMBOL(rtnl_link_get_net); | 1131 | EXPORT_SYMBOL(rtnl_link_get_net); |
1132 | 1132 | ||
1133 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | 1133 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) |
1134 | { | 1134 | { |
1135 | if (dev) { | 1135 | if (dev) { |
1136 | if (tb[IFLA_ADDRESS] && | 1136 | if (tb[IFLA_ADDRESS] && |
1137 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | 1137 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) |
1138 | return -EINVAL; | 1138 | return -EINVAL; |
1139 | 1139 | ||
1140 | if (tb[IFLA_BROADCAST] && | 1140 | if (tb[IFLA_BROADCAST] && |
1141 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | 1141 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) |
1142 | return -EINVAL; | 1142 | return -EINVAL; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | if (tb[IFLA_AF_SPEC]) { | 1145 | if (tb[IFLA_AF_SPEC]) { |
1146 | struct nlattr *af; | 1146 | struct nlattr *af; |
1147 | int rem, err; | 1147 | int rem, err; |
1148 | 1148 | ||
1149 | nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { | 1149 | nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { |
1150 | const struct rtnl_af_ops *af_ops; | 1150 | const struct rtnl_af_ops *af_ops; |
1151 | 1151 | ||
1152 | if (!(af_ops = rtnl_af_lookup(nla_type(af)))) | 1152 | if (!(af_ops = rtnl_af_lookup(nla_type(af)))) |
1153 | return -EAFNOSUPPORT; | 1153 | return -EAFNOSUPPORT; |
1154 | 1154 | ||
1155 | if (!af_ops->set_link_af) | 1155 | if (!af_ops->set_link_af) |
1156 | return -EOPNOTSUPP; | 1156 | return -EOPNOTSUPP; |
1157 | 1157 | ||
1158 | if (af_ops->validate_link_af) { | 1158 | if (af_ops->validate_link_af) { |
1159 | err = af_ops->validate_link_af(dev, af); | 1159 | err = af_ops->validate_link_af(dev, af); |
1160 | if (err < 0) | 1160 | if (err < 0) |
1161 | return err; | 1161 | return err; |
1162 | } | 1162 | } |
1163 | } | 1163 | } |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | return 0; | 1166 | return 0; |
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) | 1169 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) |
1170 | { | 1170 | { |
1171 | int rem, err = -EINVAL; | 1171 | int rem, err = -EINVAL; |
1172 | struct nlattr *vf; | 1172 | struct nlattr *vf; |
1173 | const struct net_device_ops *ops = dev->netdev_ops; | 1173 | const struct net_device_ops *ops = dev->netdev_ops; |
1174 | 1174 | ||
1175 | nla_for_each_nested(vf, attr, rem) { | 1175 | nla_for_each_nested(vf, attr, rem) { |
1176 | switch (nla_type(vf)) { | 1176 | switch (nla_type(vf)) { |
1177 | case IFLA_VF_MAC: { | 1177 | case IFLA_VF_MAC: { |
1178 | struct ifla_vf_mac *ivm; | 1178 | struct ifla_vf_mac *ivm; |
1179 | ivm = nla_data(vf); | 1179 | ivm = nla_data(vf); |
1180 | err = -EOPNOTSUPP; | 1180 | err = -EOPNOTSUPP; |
1181 | if (ops->ndo_set_vf_mac) | 1181 | if (ops->ndo_set_vf_mac) |
1182 | err = ops->ndo_set_vf_mac(dev, ivm->vf, | 1182 | err = ops->ndo_set_vf_mac(dev, ivm->vf, |
1183 | ivm->mac); | 1183 | ivm->mac); |
1184 | break; | 1184 | break; |
1185 | } | 1185 | } |
1186 | case IFLA_VF_VLAN: { | 1186 | case IFLA_VF_VLAN: { |
1187 | struct ifla_vf_vlan *ivv; | 1187 | struct ifla_vf_vlan *ivv; |
1188 | ivv = nla_data(vf); | 1188 | ivv = nla_data(vf); |
1189 | err = -EOPNOTSUPP; | 1189 | err = -EOPNOTSUPP; |
1190 | if (ops->ndo_set_vf_vlan) | 1190 | if (ops->ndo_set_vf_vlan) |
1191 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | 1191 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, |
1192 | ivv->vlan, | 1192 | ivv->vlan, |
1193 | ivv->qos); | 1193 | ivv->qos); |
1194 | break; | 1194 | break; |
1195 | } | 1195 | } |
1196 | case IFLA_VF_TX_RATE: { | 1196 | case IFLA_VF_TX_RATE: { |
1197 | struct ifla_vf_tx_rate *ivt; | 1197 | struct ifla_vf_tx_rate *ivt; |
1198 | ivt = nla_data(vf); | 1198 | ivt = nla_data(vf); |
1199 | err = -EOPNOTSUPP; | 1199 | err = -EOPNOTSUPP; |
1200 | if (ops->ndo_set_vf_tx_rate) | 1200 | if (ops->ndo_set_vf_tx_rate) |
1201 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, | 1201 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, |
1202 | ivt->rate); | 1202 | ivt->rate); |
1203 | break; | 1203 | break; |
1204 | } | 1204 | } |
1205 | default: | 1205 | default: |
1206 | err = -EINVAL; | 1206 | err = -EINVAL; |
1207 | break; | 1207 | break; |
1208 | } | 1208 | } |
1209 | if (err) | 1209 | if (err) |
1210 | break; | 1210 | break; |
1211 | } | 1211 | } |
1212 | return err; | 1212 | return err; |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | static int do_set_master(struct net_device *dev, int ifindex) | 1215 | static int do_set_master(struct net_device *dev, int ifindex) |
1216 | { | 1216 | { |
1217 | struct net_device *master_dev; | 1217 | struct net_device *master_dev; |
1218 | const struct net_device_ops *ops; | 1218 | const struct net_device_ops *ops; |
1219 | int err; | 1219 | int err; |
1220 | 1220 | ||
1221 | if (dev->master) { | 1221 | if (dev->master) { |
1222 | if (dev->master->ifindex == ifindex) | 1222 | if (dev->master->ifindex == ifindex) |
1223 | return 0; | 1223 | return 0; |
1224 | ops = dev->master->netdev_ops; | 1224 | ops = dev->master->netdev_ops; |
1225 | if (ops->ndo_del_slave) { | 1225 | if (ops->ndo_del_slave) { |
1226 | err = ops->ndo_del_slave(dev->master, dev); | 1226 | err = ops->ndo_del_slave(dev->master, dev); |
1227 | if (err) | 1227 | if (err) |
1228 | return err; | 1228 | return err; |
1229 | } else { | 1229 | } else { |
1230 | return -EOPNOTSUPP; | 1230 | return -EOPNOTSUPP; |
1231 | } | 1231 | } |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | if (ifindex) { | 1234 | if (ifindex) { |
1235 | master_dev = __dev_get_by_index(dev_net(dev), ifindex); | 1235 | master_dev = __dev_get_by_index(dev_net(dev), ifindex); |
1236 | if (!master_dev) | 1236 | if (!master_dev) |
1237 | return -EINVAL; | 1237 | return -EINVAL; |
1238 | ops = master_dev->netdev_ops; | 1238 | ops = master_dev->netdev_ops; |
1239 | if (ops->ndo_add_slave) { | 1239 | if (ops->ndo_add_slave) { |
1240 | err = ops->ndo_add_slave(master_dev, dev); | 1240 | err = ops->ndo_add_slave(master_dev, dev); |
1241 | if (err) | 1241 | if (err) |
1242 | return err; | 1242 | return err; |
1243 | } else { | 1243 | } else { |
1244 | return -EOPNOTSUPP; | 1244 | return -EOPNOTSUPP; |
1245 | } | 1245 | } |
1246 | } | 1246 | } |
1247 | return 0; | 1247 | return 0; |
1248 | } | 1248 | } |
1249 | 1249 | ||
1250 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 1250 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
1251 | struct nlattr **tb, char *ifname, int modified) | 1251 | struct nlattr **tb, char *ifname, int modified) |
1252 | { | 1252 | { |
1253 | const struct net_device_ops *ops = dev->netdev_ops; | 1253 | const struct net_device_ops *ops = dev->netdev_ops; |
1254 | int send_addr_notify = 0; | 1254 | int send_addr_notify = 0; |
1255 | int err; | 1255 | int err; |
1256 | 1256 | ||
1257 | if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { | 1257 | if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { |
1258 | struct net *net = rtnl_link_get_net(dev_net(dev), tb); | 1258 | struct net *net = rtnl_link_get_net(dev_net(dev), tb); |
1259 | if (IS_ERR(net)) { | 1259 | if (IS_ERR(net)) { |
1260 | err = PTR_ERR(net); | 1260 | err = PTR_ERR(net); |
1261 | goto errout; | 1261 | goto errout; |
1262 | } | 1262 | } |
1263 | err = dev_change_net_namespace(dev, net, ifname); | 1263 | err = dev_change_net_namespace(dev, net, ifname); |
1264 | put_net(net); | 1264 | put_net(net); |
1265 | if (err) | 1265 | if (err) |
1266 | goto errout; | 1266 | goto errout; |
1267 | modified = 1; | 1267 | modified = 1; |
1268 | } | 1268 | } |
1269 | 1269 | ||
1270 | if (tb[IFLA_MAP]) { | 1270 | if (tb[IFLA_MAP]) { |
1271 | struct rtnl_link_ifmap *u_map; | 1271 | struct rtnl_link_ifmap *u_map; |
1272 | struct ifmap k_map; | 1272 | struct ifmap k_map; |
1273 | 1273 | ||
1274 | if (!ops->ndo_set_config) { | 1274 | if (!ops->ndo_set_config) { |
1275 | err = -EOPNOTSUPP; | 1275 | err = -EOPNOTSUPP; |
1276 | goto errout; | 1276 | goto errout; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | if (!netif_device_present(dev)) { | 1279 | if (!netif_device_present(dev)) { |
1280 | err = -ENODEV; | 1280 | err = -ENODEV; |
1281 | goto errout; | 1281 | goto errout; |
1282 | } | 1282 | } |
1283 | 1283 | ||
1284 | u_map = nla_data(tb[IFLA_MAP]); | 1284 | u_map = nla_data(tb[IFLA_MAP]); |
1285 | k_map.mem_start = (unsigned long) u_map->mem_start; | 1285 | k_map.mem_start = (unsigned long) u_map->mem_start; |
1286 | k_map.mem_end = (unsigned long) u_map->mem_end; | 1286 | k_map.mem_end = (unsigned long) u_map->mem_end; |
1287 | k_map.base_addr = (unsigned short) u_map->base_addr; | 1287 | k_map.base_addr = (unsigned short) u_map->base_addr; |
1288 | k_map.irq = (unsigned char) u_map->irq; | 1288 | k_map.irq = (unsigned char) u_map->irq; |
1289 | k_map.dma = (unsigned char) u_map->dma; | 1289 | k_map.dma = (unsigned char) u_map->dma; |
1290 | k_map.port = (unsigned char) u_map->port; | 1290 | k_map.port = (unsigned char) u_map->port; |
1291 | 1291 | ||
1292 | err = ops->ndo_set_config(dev, &k_map); | 1292 | err = ops->ndo_set_config(dev, &k_map); |
1293 | if (err < 0) | 1293 | if (err < 0) |
1294 | goto errout; | 1294 | goto errout; |
1295 | 1295 | ||
1296 | modified = 1; | 1296 | modified = 1; |
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | if (tb[IFLA_ADDRESS]) { | 1299 | if (tb[IFLA_ADDRESS]) { |
1300 | struct sockaddr *sa; | 1300 | struct sockaddr *sa; |
1301 | int len; | 1301 | int len; |
1302 | 1302 | ||
1303 | if (!ops->ndo_set_mac_address) { | 1303 | if (!ops->ndo_set_mac_address) { |
1304 | err = -EOPNOTSUPP; | 1304 | err = -EOPNOTSUPP; |
1305 | goto errout; | 1305 | goto errout; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | if (!netif_device_present(dev)) { | 1308 | if (!netif_device_present(dev)) { |
1309 | err = -ENODEV; | 1309 | err = -ENODEV; |
1310 | goto errout; | 1310 | goto errout; |
1311 | } | 1311 | } |
1312 | 1312 | ||
1313 | len = sizeof(sa_family_t) + dev->addr_len; | 1313 | len = sizeof(sa_family_t) + dev->addr_len; |
1314 | sa = kmalloc(len, GFP_KERNEL); | 1314 | sa = kmalloc(len, GFP_KERNEL); |
1315 | if (!sa) { | 1315 | if (!sa) { |
1316 | err = -ENOMEM; | 1316 | err = -ENOMEM; |
1317 | goto errout; | 1317 | goto errout; |
1318 | } | 1318 | } |
1319 | sa->sa_family = dev->type; | 1319 | sa->sa_family = dev->type; |
1320 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), | 1320 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), |
1321 | dev->addr_len); | 1321 | dev->addr_len); |
1322 | err = ops->ndo_set_mac_address(dev, sa); | 1322 | err = ops->ndo_set_mac_address(dev, sa); |
1323 | kfree(sa); | 1323 | kfree(sa); |
1324 | if (err) | 1324 | if (err) |
1325 | goto errout; | 1325 | goto errout; |
1326 | send_addr_notify = 1; | 1326 | send_addr_notify = 1; |
1327 | modified = 1; | 1327 | modified = 1; |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | if (tb[IFLA_MTU]) { | 1330 | if (tb[IFLA_MTU]) { |
1331 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | 1331 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); |
1332 | if (err < 0) | 1332 | if (err < 0) |
1333 | goto errout; | 1333 | goto errout; |
1334 | modified = 1; | 1334 | modified = 1; |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | if (tb[IFLA_GROUP]) { | 1337 | if (tb[IFLA_GROUP]) { |
1338 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); | 1338 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); |
1339 | modified = 1; | 1339 | modified = 1; |
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | /* | 1342 | /* |
1343 | * Interface selected by interface index but interface | 1343 | * Interface selected by interface index but interface |
1344 | * name provided implies that a name change has been | 1344 | * name provided implies that a name change has been |
1345 | * requested. | 1345 | * requested. |
1346 | */ | 1346 | */ |
1347 | if (ifm->ifi_index > 0 && ifname[0]) { | 1347 | if (ifm->ifi_index > 0 && ifname[0]) { |
1348 | err = dev_change_name(dev, ifname); | 1348 | err = dev_change_name(dev, ifname); |
1349 | if (err < 0) | 1349 | if (err < 0) |
1350 | goto errout; | 1350 | goto errout; |
1351 | modified = 1; | 1351 | modified = 1; |
1352 | } | 1352 | } |
1353 | 1353 | ||
1354 | if (tb[IFLA_IFALIAS]) { | 1354 | if (tb[IFLA_IFALIAS]) { |
1355 | err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), | 1355 | err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), |
1356 | nla_len(tb[IFLA_IFALIAS])); | 1356 | nla_len(tb[IFLA_IFALIAS])); |
1357 | if (err < 0) | 1357 | if (err < 0) |
1358 | goto errout; | 1358 | goto errout; |
1359 | modified = 1; | 1359 | modified = 1; |
1360 | } | 1360 | } |
1361 | 1361 | ||
1362 | if (tb[IFLA_BROADCAST]) { | 1362 | if (tb[IFLA_BROADCAST]) { |
1363 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); | 1363 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); |
1364 | send_addr_notify = 1; | 1364 | send_addr_notify = 1; |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | if (ifm->ifi_flags || ifm->ifi_change) { | 1367 | if (ifm->ifi_flags || ifm->ifi_change) { |
1368 | err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); | 1368 | err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); |
1369 | if (err < 0) | 1369 | if (err < 0) |
1370 | goto errout; | 1370 | goto errout; |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | if (tb[IFLA_MASTER]) { | 1373 | if (tb[IFLA_MASTER]) { |
1374 | err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); | 1374 | err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); |
1375 | if (err) | 1375 | if (err) |
1376 | goto errout; | 1376 | goto errout; |
1377 | modified = 1; | 1377 | modified = 1; |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | if (tb[IFLA_TXQLEN]) | 1380 | if (tb[IFLA_TXQLEN]) |
1381 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | 1381 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); |
1382 | 1382 | ||
1383 | if (tb[IFLA_OPERSTATE]) | 1383 | if (tb[IFLA_OPERSTATE]) |
1384 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | 1384 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); |
1385 | 1385 | ||
1386 | if (tb[IFLA_LINKMODE]) { | 1386 | if (tb[IFLA_LINKMODE]) { |
1387 | write_lock_bh(&dev_base_lock); | 1387 | write_lock_bh(&dev_base_lock); |
1388 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | 1388 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); |
1389 | write_unlock_bh(&dev_base_lock); | 1389 | write_unlock_bh(&dev_base_lock); |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | if (tb[IFLA_VFINFO_LIST]) { | 1392 | if (tb[IFLA_VFINFO_LIST]) { |
1393 | struct nlattr *attr; | 1393 | struct nlattr *attr; |
1394 | int rem; | 1394 | int rem; |
1395 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { | 1395 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { |
1396 | if (nla_type(attr) != IFLA_VF_INFO) { | 1396 | if (nla_type(attr) != IFLA_VF_INFO) { |
1397 | err = -EINVAL; | 1397 | err = -EINVAL; |
1398 | goto errout; | 1398 | goto errout; |
1399 | } | 1399 | } |
1400 | err = do_setvfinfo(dev, attr); | 1400 | err = do_setvfinfo(dev, attr); |
1401 | if (err < 0) | 1401 | if (err < 0) |
1402 | goto errout; | 1402 | goto errout; |
1403 | modified = 1; | 1403 | modified = 1; |
1404 | } | 1404 | } |
1405 | } | 1405 | } |
1406 | err = 0; | 1406 | err = 0; |
1407 | 1407 | ||
1408 | if (tb[IFLA_VF_PORTS]) { | 1408 | if (tb[IFLA_VF_PORTS]) { |
1409 | struct nlattr *port[IFLA_PORT_MAX+1]; | 1409 | struct nlattr *port[IFLA_PORT_MAX+1]; |
1410 | struct nlattr *attr; | 1410 | struct nlattr *attr; |
1411 | int vf; | 1411 | int vf; |
1412 | int rem; | 1412 | int rem; |
1413 | 1413 | ||
1414 | err = -EOPNOTSUPP; | 1414 | err = -EOPNOTSUPP; |
1415 | if (!ops->ndo_set_vf_port) | 1415 | if (!ops->ndo_set_vf_port) |
1416 | goto errout; | 1416 | goto errout; |
1417 | 1417 | ||
1418 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { | 1418 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { |
1419 | if (nla_type(attr) != IFLA_VF_PORT) | 1419 | if (nla_type(attr) != IFLA_VF_PORT) |
1420 | continue; | 1420 | continue; |
1421 | err = nla_parse_nested(port, IFLA_PORT_MAX, | 1421 | err = nla_parse_nested(port, IFLA_PORT_MAX, |
1422 | attr, ifla_port_policy); | 1422 | attr, ifla_port_policy); |
1423 | if (err < 0) | 1423 | if (err < 0) |
1424 | goto errout; | 1424 | goto errout; |
1425 | if (!port[IFLA_PORT_VF]) { | 1425 | if (!port[IFLA_PORT_VF]) { |
1426 | err = -EOPNOTSUPP; | 1426 | err = -EOPNOTSUPP; |
1427 | goto errout; | 1427 | goto errout; |
1428 | } | 1428 | } |
1429 | vf = nla_get_u32(port[IFLA_PORT_VF]); | 1429 | vf = nla_get_u32(port[IFLA_PORT_VF]); |
1430 | err = ops->ndo_set_vf_port(dev, vf, port); | 1430 | err = ops->ndo_set_vf_port(dev, vf, port); |
1431 | if (err < 0) | 1431 | if (err < 0) |
1432 | goto errout; | 1432 | goto errout; |
1433 | modified = 1; | 1433 | modified = 1; |
1434 | } | 1434 | } |
1435 | } | 1435 | } |
1436 | err = 0; | 1436 | err = 0; |
1437 | 1437 | ||
1438 | if (tb[IFLA_PORT_SELF]) { | 1438 | if (tb[IFLA_PORT_SELF]) { |
1439 | struct nlattr *port[IFLA_PORT_MAX+1]; | 1439 | struct nlattr *port[IFLA_PORT_MAX+1]; |
1440 | 1440 | ||
1441 | err = nla_parse_nested(port, IFLA_PORT_MAX, | 1441 | err = nla_parse_nested(port, IFLA_PORT_MAX, |
1442 | tb[IFLA_PORT_SELF], ifla_port_policy); | 1442 | tb[IFLA_PORT_SELF], ifla_port_policy); |
1443 | if (err < 0) | 1443 | if (err < 0) |
1444 | goto errout; | 1444 | goto errout; |
1445 | 1445 | ||
1446 | err = -EOPNOTSUPP; | 1446 | err = -EOPNOTSUPP; |
1447 | if (ops->ndo_set_vf_port) | 1447 | if (ops->ndo_set_vf_port) |
1448 | err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); | 1448 | err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); |
1449 | if (err < 0) | 1449 | if (err < 0) |
1450 | goto errout; | 1450 | goto errout; |
1451 | modified = 1; | 1451 | modified = 1; |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | if (tb[IFLA_AF_SPEC]) { | 1454 | if (tb[IFLA_AF_SPEC]) { |
1455 | struct nlattr *af; | 1455 | struct nlattr *af; |
1456 | int rem; | 1456 | int rem; |
1457 | 1457 | ||
1458 | nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { | 1458 | nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { |
1459 | const struct rtnl_af_ops *af_ops; | 1459 | const struct rtnl_af_ops *af_ops; |
1460 | 1460 | ||
1461 | if (!(af_ops = rtnl_af_lookup(nla_type(af)))) | 1461 | if (!(af_ops = rtnl_af_lookup(nla_type(af)))) |
1462 | BUG(); | 1462 | BUG(); |
1463 | 1463 | ||
1464 | err = af_ops->set_link_af(dev, af); | 1464 | err = af_ops->set_link_af(dev, af); |
1465 | if (err < 0) | 1465 | if (err < 0) |
1466 | goto errout; | 1466 | goto errout; |
1467 | 1467 | ||
1468 | modified = 1; | 1468 | modified = 1; |
1469 | } | 1469 | } |
1470 | } | 1470 | } |
1471 | err = 0; | 1471 | err = 0; |
1472 | 1472 | ||
1473 | errout: | 1473 | errout: |
1474 | if (err < 0 && modified && net_ratelimit()) | 1474 | if (err < 0 && modified && net_ratelimit()) |
1475 | printk(KERN_WARNING "A link change request failed with " | 1475 | printk(KERN_WARNING "A link change request failed with " |
1476 | "some changes committed already. Interface %s may " | 1476 | "some changes committed already. Interface %s may " |
1477 | "have been left with an inconsistent configuration, " | 1477 | "have been left with an inconsistent configuration, " |
1478 | "please check.\n", dev->name); | 1478 | "please check.\n", dev->name); |
1479 | 1479 | ||
1480 | if (send_addr_notify) | 1480 | if (send_addr_notify) |
1481 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 1481 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
1482 | return err; | 1482 | return err; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1485 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1486 | { | 1486 | { |
1487 | struct net *net = sock_net(skb->sk); | 1487 | struct net *net = sock_net(skb->sk); |
1488 | struct ifinfomsg *ifm; | 1488 | struct ifinfomsg *ifm; |
1489 | struct net_device *dev; | 1489 | struct net_device *dev; |
1490 | int err; | 1490 | int err; |
1491 | struct nlattr *tb[IFLA_MAX+1]; | 1491 | struct nlattr *tb[IFLA_MAX+1]; |
1492 | char ifname[IFNAMSIZ]; | 1492 | char ifname[IFNAMSIZ]; |
1493 | 1493 | ||
1494 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | 1494 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
1495 | if (err < 0) | 1495 | if (err < 0) |
1496 | goto errout; | 1496 | goto errout; |
1497 | 1497 | ||
1498 | if (tb[IFLA_IFNAME]) | 1498 | if (tb[IFLA_IFNAME]) |
1499 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | 1499 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); |
1500 | else | 1500 | else |
1501 | ifname[0] = '\0'; | 1501 | ifname[0] = '\0'; |
1502 | 1502 | ||
1503 | err = -EINVAL; | 1503 | err = -EINVAL; |
1504 | ifm = nlmsg_data(nlh); | 1504 | ifm = nlmsg_data(nlh); |
1505 | if (ifm->ifi_index > 0) | 1505 | if (ifm->ifi_index > 0) |
1506 | dev = __dev_get_by_index(net, ifm->ifi_index); | 1506 | dev = __dev_get_by_index(net, ifm->ifi_index); |
1507 | else if (tb[IFLA_IFNAME]) | 1507 | else if (tb[IFLA_IFNAME]) |
1508 | dev = __dev_get_by_name(net, ifname); | 1508 | dev = __dev_get_by_name(net, ifname); |
1509 | else | 1509 | else |
1510 | goto errout; | 1510 | goto errout; |
1511 | 1511 | ||
1512 | if (dev == NULL) { | 1512 | if (dev == NULL) { |
1513 | err = -ENODEV; | 1513 | err = -ENODEV; |
1514 | goto errout; | 1514 | goto errout; |
1515 | } | 1515 | } |
1516 | 1516 | ||
1517 | err = validate_linkmsg(dev, tb); | 1517 | err = validate_linkmsg(dev, tb); |
1518 | if (err < 0) | 1518 | if (err < 0) |
1519 | goto errout; | 1519 | goto errout; |
1520 | 1520 | ||
1521 | err = do_setlink(dev, ifm, tb, ifname, 0); | 1521 | err = do_setlink(dev, ifm, tb, ifname, 0); |
1522 | errout: | 1522 | errout: |
1523 | return err; | 1523 | return err; |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1526 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1527 | { | 1527 | { |
1528 | struct net *net = sock_net(skb->sk); | 1528 | struct net *net = sock_net(skb->sk); |
1529 | const struct rtnl_link_ops *ops; | 1529 | const struct rtnl_link_ops *ops; |
1530 | struct net_device *dev; | 1530 | struct net_device *dev; |
1531 | struct ifinfomsg *ifm; | 1531 | struct ifinfomsg *ifm; |
1532 | char ifname[IFNAMSIZ]; | 1532 | char ifname[IFNAMSIZ]; |
1533 | struct nlattr *tb[IFLA_MAX+1]; | 1533 | struct nlattr *tb[IFLA_MAX+1]; |
1534 | int err; | 1534 | int err; |
1535 | LIST_HEAD(list_kill); | 1535 | LIST_HEAD(list_kill); |
1536 | 1536 | ||
1537 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | 1537 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
1538 | if (err < 0) | 1538 | if (err < 0) |
1539 | return err; | 1539 | return err; |
1540 | 1540 | ||
1541 | if (tb[IFLA_IFNAME]) | 1541 | if (tb[IFLA_IFNAME]) |
1542 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | 1542 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); |
1543 | 1543 | ||
1544 | ifm = nlmsg_data(nlh); | 1544 | ifm = nlmsg_data(nlh); |
1545 | if (ifm->ifi_index > 0) | 1545 | if (ifm->ifi_index > 0) |
1546 | dev = __dev_get_by_index(net, ifm->ifi_index); | 1546 | dev = __dev_get_by_index(net, ifm->ifi_index); |
1547 | else if (tb[IFLA_IFNAME]) | 1547 | else if (tb[IFLA_IFNAME]) |
1548 | dev = __dev_get_by_name(net, ifname); | 1548 | dev = __dev_get_by_name(net, ifname); |
1549 | else | 1549 | else |
1550 | return -EINVAL; | 1550 | return -EINVAL; |
1551 | 1551 | ||
1552 | if (!dev) | 1552 | if (!dev) |
1553 | return -ENODEV; | 1553 | return -ENODEV; |
1554 | 1554 | ||
1555 | ops = dev->rtnl_link_ops; | 1555 | ops = dev->rtnl_link_ops; |
1556 | if (!ops) | 1556 | if (!ops) |
1557 | return -EOPNOTSUPP; | 1557 | return -EOPNOTSUPP; |
1558 | 1558 | ||
1559 | ops->dellink(dev, &list_kill); | 1559 | ops->dellink(dev, &list_kill); |
1560 | unregister_netdevice_many(&list_kill); | 1560 | unregister_netdevice_many(&list_kill); |
1561 | list_del(&list_kill); | 1561 | list_del(&list_kill); |
1562 | return 0; | 1562 | return 0; |
1563 | } | 1563 | } |
1564 | 1564 | ||
1565 | int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) | 1565 | int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) |
1566 | { | 1566 | { |
1567 | unsigned int old_flags; | 1567 | unsigned int old_flags; |
1568 | int err; | 1568 | int err; |
1569 | 1569 | ||
1570 | old_flags = dev->flags; | 1570 | old_flags = dev->flags; |
1571 | if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { | 1571 | if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { |
1572 | err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); | 1572 | err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); |
1573 | if (err < 0) | 1573 | if (err < 0) |
1574 | return err; | 1574 | return err; |
1575 | } | 1575 | } |
1576 | 1576 | ||
1577 | dev->rtnl_link_state = RTNL_LINK_INITIALIZED; | 1577 | dev->rtnl_link_state = RTNL_LINK_INITIALIZED; |
1578 | rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); | 1578 | rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); |
1579 | 1579 | ||
1580 | __dev_notify_flags(dev, old_flags); | 1580 | __dev_notify_flags(dev, old_flags); |
1581 | return 0; | 1581 | return 0; |
1582 | } | 1582 | } |
1583 | EXPORT_SYMBOL(rtnl_configure_link); | 1583 | EXPORT_SYMBOL(rtnl_configure_link); |
1584 | 1584 | ||
1585 | struct net_device *rtnl_create_link(struct net *src_net, struct net *net, | 1585 | struct net_device *rtnl_create_link(struct net *src_net, struct net *net, |
1586 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 1586 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) |
1587 | { | 1587 | { |
1588 | int err; | 1588 | int err; |
1589 | struct net_device *dev; | 1589 | struct net_device *dev; |
1590 | unsigned int num_queues = 1; | 1590 | unsigned int num_queues = 1; |
1591 | unsigned int real_num_queues = 1; | 1591 | unsigned int real_num_queues = 1; |
1592 | 1592 | ||
1593 | if (ops->get_tx_queues) { | 1593 | if (ops->get_tx_queues) { |
1594 | err = ops->get_tx_queues(src_net, tb, &num_queues, | 1594 | err = ops->get_tx_queues(src_net, tb, &num_queues, |
1595 | &real_num_queues); | 1595 | &real_num_queues); |
1596 | if (err) | 1596 | if (err) |
1597 | goto err; | 1597 | goto err; |
1598 | } | 1598 | } |
1599 | err = -ENOMEM; | 1599 | err = -ENOMEM; |
1600 | dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues); | 1600 | dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues); |
1601 | if (!dev) | 1601 | if (!dev) |
1602 | goto err; | 1602 | goto err; |
1603 | 1603 | ||
1604 | dev_net_set(dev, net); | 1604 | dev_net_set(dev, net); |
1605 | dev->rtnl_link_ops = ops; | 1605 | dev->rtnl_link_ops = ops; |
1606 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; | 1606 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; |
1607 | dev->real_num_tx_queues = real_num_queues; | 1607 | dev->real_num_tx_queues = real_num_queues; |
1608 | 1608 | ||
1609 | if (tb[IFLA_MTU]) | 1609 | if (tb[IFLA_MTU]) |
1610 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | 1610 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
1611 | if (tb[IFLA_ADDRESS]) | 1611 | if (tb[IFLA_ADDRESS]) |
1612 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), | 1612 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), |
1613 | nla_len(tb[IFLA_ADDRESS])); | 1613 | nla_len(tb[IFLA_ADDRESS])); |
1614 | if (tb[IFLA_BROADCAST]) | 1614 | if (tb[IFLA_BROADCAST]) |
1615 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), | 1615 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), |
1616 | nla_len(tb[IFLA_BROADCAST])); | 1616 | nla_len(tb[IFLA_BROADCAST])); |
1617 | if (tb[IFLA_TXQLEN]) | 1617 | if (tb[IFLA_TXQLEN]) |
1618 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | 1618 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); |
1619 | if (tb[IFLA_OPERSTATE]) | 1619 | if (tb[IFLA_OPERSTATE]) |
1620 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | 1620 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); |
1621 | if (tb[IFLA_LINKMODE]) | 1621 | if (tb[IFLA_LINKMODE]) |
1622 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | 1622 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); |
1623 | if (tb[IFLA_GROUP]) | 1623 | if (tb[IFLA_GROUP]) |
1624 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); | 1624 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); |
1625 | 1625 | ||
1626 | return dev; | 1626 | return dev; |
1627 | 1627 | ||
1628 | err: | 1628 | err: |
1629 | return ERR_PTR(err); | 1629 | return ERR_PTR(err); |
1630 | } | 1630 | } |
1631 | EXPORT_SYMBOL(rtnl_create_link); | 1631 | EXPORT_SYMBOL(rtnl_create_link); |
1632 | 1632 | ||
1633 | static int rtnl_group_changelink(struct net *net, int group, | 1633 | static int rtnl_group_changelink(struct net *net, int group, |
1634 | struct ifinfomsg *ifm, | 1634 | struct ifinfomsg *ifm, |
1635 | struct nlattr **tb) | 1635 | struct nlattr **tb) |
1636 | { | 1636 | { |
1637 | struct net_device *dev; | 1637 | struct net_device *dev; |
1638 | int err; | 1638 | int err; |
1639 | 1639 | ||
1640 | for_each_netdev(net, dev) { | 1640 | for_each_netdev(net, dev) { |
1641 | if (dev->group == group) { | 1641 | if (dev->group == group) { |
1642 | err = do_setlink(dev, ifm, tb, NULL, 0); | 1642 | err = do_setlink(dev, ifm, tb, NULL, 0); |
1643 | if (err < 0) | 1643 | if (err < 0) |
1644 | return err; | 1644 | return err; |
1645 | } | 1645 | } |
1646 | } | 1646 | } |
1647 | 1647 | ||
1648 | return 0; | 1648 | return 0; |
1649 | } | 1649 | } |
1650 | 1650 | ||
1651 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1651 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1652 | { | 1652 | { |
1653 | struct net *net = sock_net(skb->sk); | 1653 | struct net *net = sock_net(skb->sk); |
1654 | const struct rtnl_link_ops *ops; | 1654 | const struct rtnl_link_ops *ops; |
1655 | struct net_device *dev; | 1655 | struct net_device *dev; |
1656 | struct ifinfomsg *ifm; | 1656 | struct ifinfomsg *ifm; |
1657 | char kind[MODULE_NAME_LEN]; | 1657 | char kind[MODULE_NAME_LEN]; |
1658 | char ifname[IFNAMSIZ]; | 1658 | char ifname[IFNAMSIZ]; |
1659 | struct nlattr *tb[IFLA_MAX+1]; | 1659 | struct nlattr *tb[IFLA_MAX+1]; |
1660 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; | 1660 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; |
1661 | int err; | 1661 | int err; |
1662 | 1662 | ||
1663 | #ifdef CONFIG_MODULES | 1663 | #ifdef CONFIG_MODULES |
1664 | replay: | 1664 | replay: |
1665 | #endif | 1665 | #endif |
1666 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | 1666 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
1667 | if (err < 0) | 1667 | if (err < 0) |
1668 | return err; | 1668 | return err; |
1669 | 1669 | ||
1670 | if (tb[IFLA_IFNAME]) | 1670 | if (tb[IFLA_IFNAME]) |
1671 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | 1671 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); |
1672 | else | 1672 | else |
1673 | ifname[0] = '\0'; | 1673 | ifname[0] = '\0'; |
1674 | 1674 | ||
1675 | ifm = nlmsg_data(nlh); | 1675 | ifm = nlmsg_data(nlh); |
1676 | if (ifm->ifi_index > 0) | 1676 | if (ifm->ifi_index > 0) |
1677 | dev = __dev_get_by_index(net, ifm->ifi_index); | 1677 | dev = __dev_get_by_index(net, ifm->ifi_index); |
1678 | else { | 1678 | else { |
1679 | if (ifname[0]) | 1679 | if (ifname[0]) |
1680 | dev = __dev_get_by_name(net, ifname); | 1680 | dev = __dev_get_by_name(net, ifname); |
1681 | else | 1681 | else |
1682 | dev = NULL; | 1682 | dev = NULL; |
1683 | } | 1683 | } |
1684 | 1684 | ||
1685 | err = validate_linkmsg(dev, tb); | 1685 | err = validate_linkmsg(dev, tb); |
1686 | if (err < 0) | 1686 | if (err < 0) |
1687 | return err; | 1687 | return err; |
1688 | 1688 | ||
1689 | if (tb[IFLA_LINKINFO]) { | 1689 | if (tb[IFLA_LINKINFO]) { |
1690 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, | 1690 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, |
1691 | tb[IFLA_LINKINFO], ifla_info_policy); | 1691 | tb[IFLA_LINKINFO], ifla_info_policy); |
1692 | if (err < 0) | 1692 | if (err < 0) |
1693 | return err; | 1693 | return err; |
1694 | } else | 1694 | } else |
1695 | memset(linkinfo, 0, sizeof(linkinfo)); | 1695 | memset(linkinfo, 0, sizeof(linkinfo)); |
1696 | 1696 | ||
1697 | if (linkinfo[IFLA_INFO_KIND]) { | 1697 | if (linkinfo[IFLA_INFO_KIND]) { |
1698 | nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); | 1698 | nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); |
1699 | ops = rtnl_link_ops_get(kind); | 1699 | ops = rtnl_link_ops_get(kind); |
1700 | } else { | 1700 | } else { |
1701 | kind[0] = '\0'; | 1701 | kind[0] = '\0'; |
1702 | ops = NULL; | 1702 | ops = NULL; |
1703 | } | 1703 | } |
1704 | 1704 | ||
1705 | if (1) { | 1705 | if (1) { |
1706 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | 1706 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; |
1707 | struct net *dest_net; | 1707 | struct net *dest_net; |
1708 | 1708 | ||
1709 | if (ops) { | 1709 | if (ops) { |
1710 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | 1710 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { |
1711 | err = nla_parse_nested(attr, ops->maxtype, | 1711 | err = nla_parse_nested(attr, ops->maxtype, |
1712 | linkinfo[IFLA_INFO_DATA], | 1712 | linkinfo[IFLA_INFO_DATA], |
1713 | ops->policy); | 1713 | ops->policy); |
1714 | if (err < 0) | 1714 | if (err < 0) |
1715 | return err; | 1715 | return err; |
1716 | data = attr; | 1716 | data = attr; |
1717 | } | 1717 | } |
1718 | if (ops->validate) { | 1718 | if (ops->validate) { |
1719 | err = ops->validate(tb, data); | 1719 | err = ops->validate(tb, data); |
1720 | if (err < 0) | 1720 | if (err < 0) |
1721 | return err; | 1721 | return err; |
1722 | } | 1722 | } |
1723 | } | 1723 | } |
1724 | 1724 | ||
1725 | if (dev) { | 1725 | if (dev) { |
1726 | int modified = 0; | 1726 | int modified = 0; |
1727 | 1727 | ||
1728 | if (nlh->nlmsg_flags & NLM_F_EXCL) | 1728 | if (nlh->nlmsg_flags & NLM_F_EXCL) |
1729 | return -EEXIST; | 1729 | return -EEXIST; |
1730 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | 1730 | if (nlh->nlmsg_flags & NLM_F_REPLACE) |
1731 | return -EOPNOTSUPP; | 1731 | return -EOPNOTSUPP; |
1732 | 1732 | ||
1733 | if (linkinfo[IFLA_INFO_DATA]) { | 1733 | if (linkinfo[IFLA_INFO_DATA]) { |
1734 | if (!ops || ops != dev->rtnl_link_ops || | 1734 | if (!ops || ops != dev->rtnl_link_ops || |
1735 | !ops->changelink) | 1735 | !ops->changelink) |
1736 | return -EOPNOTSUPP; | 1736 | return -EOPNOTSUPP; |
1737 | 1737 | ||
1738 | err = ops->changelink(dev, tb, data); | 1738 | err = ops->changelink(dev, tb, data); |
1739 | if (err < 0) | 1739 | if (err < 0) |
1740 | return err; | 1740 | return err; |
1741 | modified = 1; | 1741 | modified = 1; |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | return do_setlink(dev, ifm, tb, ifname, modified); | 1744 | return do_setlink(dev, ifm, tb, ifname, modified); |
1745 | } | 1745 | } |
1746 | 1746 | ||
1747 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | 1747 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { |
1748 | if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) | 1748 | if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) |
1749 | return rtnl_group_changelink(net, | 1749 | return rtnl_group_changelink(net, |
1750 | nla_get_u32(tb[IFLA_GROUP]), | 1750 | nla_get_u32(tb[IFLA_GROUP]), |
1751 | ifm, tb); | 1751 | ifm, tb); |
1752 | return -ENODEV; | 1752 | return -ENODEV; |
1753 | } | 1753 | } |
1754 | 1754 | ||
1755 | if (ifm->ifi_index) | 1755 | if (ifm->ifi_index) |
1756 | return -EOPNOTSUPP; | 1756 | return -EOPNOTSUPP; |
1757 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) | 1757 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) |
1758 | return -EOPNOTSUPP; | 1758 | return -EOPNOTSUPP; |
1759 | 1759 | ||
1760 | if (!ops) { | 1760 | if (!ops) { |
1761 | #ifdef CONFIG_MODULES | 1761 | #ifdef CONFIG_MODULES |
1762 | if (kind[0]) { | 1762 | if (kind[0]) { |
1763 | __rtnl_unlock(); | 1763 | __rtnl_unlock(); |
1764 | request_module("rtnl-link-%s", kind); | 1764 | request_module("rtnl-link-%s", kind); |
1765 | rtnl_lock(); | 1765 | rtnl_lock(); |
1766 | ops = rtnl_link_ops_get(kind); | 1766 | ops = rtnl_link_ops_get(kind); |
1767 | if (ops) | 1767 | if (ops) |
1768 | goto replay; | 1768 | goto replay; |
1769 | } | 1769 | } |
1770 | #endif | 1770 | #endif |
1771 | return -EOPNOTSUPP; | 1771 | return -EOPNOTSUPP; |
1772 | } | 1772 | } |
1773 | 1773 | ||
1774 | if (!ifname[0]) | 1774 | if (!ifname[0]) |
1775 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 1775 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
1776 | 1776 | ||
1777 | dest_net = rtnl_link_get_net(net, tb); | 1777 | dest_net = rtnl_link_get_net(net, tb); |
1778 | if (IS_ERR(dest_net)) | 1778 | if (IS_ERR(dest_net)) |
1779 | return PTR_ERR(dest_net); | 1779 | return PTR_ERR(dest_net); |
1780 | 1780 | ||
1781 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); | 1781 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); |
1782 | 1782 | ||
1783 | if (IS_ERR(dev)) | 1783 | if (IS_ERR(dev)) |
1784 | err = PTR_ERR(dev); | 1784 | err = PTR_ERR(dev); |
1785 | else if (ops->newlink) | 1785 | else if (ops->newlink) |
1786 | err = ops->newlink(net, dev, tb, data); | 1786 | err = ops->newlink(net, dev, tb, data); |
1787 | else | 1787 | else |
1788 | err = register_netdevice(dev); | 1788 | err = register_netdevice(dev); |
1789 | 1789 | ||
1790 | if (err < 0 && !IS_ERR(dev)) | 1790 | if (err < 0 && !IS_ERR(dev)) |
1791 | free_netdev(dev); | 1791 | free_netdev(dev); |
1792 | if (err < 0) | 1792 | if (err < 0) |
1793 | goto out; | 1793 | goto out; |
1794 | 1794 | ||
1795 | err = rtnl_configure_link(dev, ifm); | 1795 | err = rtnl_configure_link(dev, ifm); |
1796 | if (err < 0) | 1796 | if (err < 0) |
1797 | unregister_netdevice(dev); | 1797 | unregister_netdevice(dev); |
1798 | out: | 1798 | out: |
1799 | put_net(dest_net); | 1799 | put_net(dest_net); |
1800 | return err; | 1800 | return err; |
1801 | } | 1801 | } |
1802 | } | 1802 | } |
1803 | 1803 | ||
1804 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 1804 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
1805 | { | 1805 | { |
1806 | struct net *net = sock_net(skb->sk); | 1806 | struct net *net = sock_net(skb->sk); |
1807 | struct ifinfomsg *ifm; | 1807 | struct ifinfomsg *ifm; |
1808 | char ifname[IFNAMSIZ]; | 1808 | char ifname[IFNAMSIZ]; |
1809 | struct nlattr *tb[IFLA_MAX+1]; | 1809 | struct nlattr *tb[IFLA_MAX+1]; |
1810 | struct net_device *dev = NULL; | 1810 | struct net_device *dev = NULL; |
1811 | struct sk_buff *nskb; | 1811 | struct sk_buff *nskb; |
1812 | int err; | 1812 | int err; |
1813 | 1813 | ||
1814 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | 1814 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
1815 | if (err < 0) | 1815 | if (err < 0) |
1816 | return err; | 1816 | return err; |
1817 | 1817 | ||
1818 | if (tb[IFLA_IFNAME]) | 1818 | if (tb[IFLA_IFNAME]) |
1819 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | 1819 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); |
1820 | 1820 | ||
1821 | ifm = nlmsg_data(nlh); | 1821 | ifm = nlmsg_data(nlh); |
1822 | if (ifm->ifi_index > 0) | 1822 | if (ifm->ifi_index > 0) |
1823 | dev = __dev_get_by_index(net, ifm->ifi_index); | 1823 | dev = __dev_get_by_index(net, ifm->ifi_index); |
1824 | else if (tb[IFLA_IFNAME]) | 1824 | else if (tb[IFLA_IFNAME]) |
1825 | dev = __dev_get_by_name(net, ifname); | 1825 | dev = __dev_get_by_name(net, ifname); |
1826 | else | 1826 | else |
1827 | return -EINVAL; | 1827 | return -EINVAL; |
1828 | 1828 | ||
1829 | if (dev == NULL) | 1829 | if (dev == NULL) |
1830 | return -ENODEV; | 1830 | return -ENODEV; |
1831 | 1831 | ||
1832 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); | 1832 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
1833 | if (nskb == NULL) | 1833 | if (nskb == NULL) |
1834 | return -ENOBUFS; | 1834 | return -ENOBUFS; |
1835 | 1835 | ||
1836 | err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, | 1836 | err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, |
1837 | nlh->nlmsg_seq, 0, 0); | 1837 | nlh->nlmsg_seq, 0, 0); |
1838 | if (err < 0) { | 1838 | if (err < 0) { |
1839 | /* -EMSGSIZE implies BUG in if_nlmsg_size */ | 1839 | /* -EMSGSIZE implies BUG in if_nlmsg_size */ |
1840 | WARN_ON(err == -EMSGSIZE); | 1840 | WARN_ON(err == -EMSGSIZE); |
1841 | kfree_skb(nskb); | 1841 | kfree_skb(nskb); |
1842 | } else | 1842 | } else |
1843 | err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); | 1843 | err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); |
1844 | 1844 | ||
1845 | return err; | 1845 | return err; |
1846 | } | 1846 | } |
1847 | 1847 | ||
1848 | static u16 rtnl_calcit(struct sk_buff *skb) | 1848 | static u16 rtnl_calcit(struct sk_buff *skb) |
1849 | { | 1849 | { |
1850 | return min_ifinfo_dump_size; | 1850 | return min_ifinfo_dump_size; |
1851 | } | 1851 | } |
1852 | 1852 | ||
1853 | static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | 1853 | static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) |
1854 | { | 1854 | { |
1855 | int idx; | 1855 | int idx; |
1856 | int s_idx = cb->family; | 1856 | int s_idx = cb->family; |
1857 | 1857 | ||
1858 | if (s_idx == 0) | 1858 | if (s_idx == 0) |
1859 | s_idx = 1; | 1859 | s_idx = 1; |
1860 | for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { | 1860 | for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { |
1861 | int type = cb->nlh->nlmsg_type-RTM_BASE; | 1861 | int type = cb->nlh->nlmsg_type-RTM_BASE; |
1862 | if (idx < s_idx || idx == PF_PACKET) | 1862 | if (idx < s_idx || idx == PF_PACKET) |
1863 | continue; | 1863 | continue; |
1864 | if (rtnl_msg_handlers[idx] == NULL || | 1864 | if (rtnl_msg_handlers[idx] == NULL || |
1865 | rtnl_msg_handlers[idx][type].dumpit == NULL) | 1865 | rtnl_msg_handlers[idx][type].dumpit == NULL) |
1866 | continue; | 1866 | continue; |
1867 | if (idx > s_idx) | 1867 | if (idx > s_idx) |
1868 | memset(&cb->args[0], 0, sizeof(cb->args)); | 1868 | memset(&cb->args[0], 0, sizeof(cb->args)); |
1869 | if (rtnl_msg_handlers[idx][type].dumpit(skb, cb)) | 1869 | if (rtnl_msg_handlers[idx][type].dumpit(skb, cb)) |
1870 | break; | 1870 | break; |
1871 | } | 1871 | } |
1872 | cb->family = idx; | 1872 | cb->family = idx; |
1873 | 1873 | ||
1874 | return skb->len; | 1874 | return skb->len; |
1875 | } | 1875 | } |
1876 | 1876 | ||
1877 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | 1877 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) |
1878 | { | 1878 | { |
1879 | struct net *net = dev_net(dev); | 1879 | struct net *net = dev_net(dev); |
1880 | struct sk_buff *skb; | 1880 | struct sk_buff *skb; |
1881 | int err = -ENOBUFS; | 1881 | int err = -ENOBUFS; |
1882 | size_t if_info_size; | 1882 | size_t if_info_size; |
1883 | 1883 | ||
1884 | skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL); | 1884 | skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL); |
1885 | if (skb == NULL) | 1885 | if (skb == NULL) |
1886 | goto errout; | 1886 | goto errout; |
1887 | 1887 | ||
1888 | min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size); | 1888 | min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size); |
1889 | 1889 | ||
1890 | err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); | 1890 | err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); |
1891 | if (err < 0) { | 1891 | if (err < 0) { |
1892 | /* -EMSGSIZE implies BUG in if_nlmsg_size() */ | 1892 | /* -EMSGSIZE implies BUG in if_nlmsg_size() */ |
1893 | WARN_ON(err == -EMSGSIZE); | 1893 | WARN_ON(err == -EMSGSIZE); |
1894 | kfree_skb(skb); | 1894 | kfree_skb(skb); |
1895 | goto errout; | 1895 | goto errout; |
1896 | } | 1896 | } |
1897 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); | 1897 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); |
1898 | return; | 1898 | return; |
1899 | errout: | 1899 | errout: |
1900 | if (err < 0) | 1900 | if (err < 0) |
1901 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 1901 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
1902 | } | 1902 | } |
1903 | 1903 | ||
1904 | /* Protected by RTNL sempahore. */ | 1904 | /* Protected by RTNL sempahore. */ |
1905 | static struct rtattr **rta_buf; | 1905 | static struct rtattr **rta_buf; |
1906 | static int rtattr_max; | 1906 | static int rtattr_max; |
1907 | 1907 | ||
1908 | /* Process one rtnetlink message. */ | 1908 | /* Process one rtnetlink message. */ |
1909 | 1909 | ||
1910 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 1910 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
1911 | { | 1911 | { |
1912 | struct net *net = sock_net(skb->sk); | 1912 | struct net *net = sock_net(skb->sk); |
1913 | rtnl_doit_func doit; | 1913 | rtnl_doit_func doit; |
1914 | int sz_idx, kind; | 1914 | int sz_idx, kind; |
1915 | int min_len; | 1915 | int min_len; |
1916 | int family; | 1916 | int family; |
1917 | int type; | 1917 | int type; |
1918 | int err; | 1918 | int err; |
1919 | 1919 | ||
1920 | type = nlh->nlmsg_type; | 1920 | type = nlh->nlmsg_type; |
1921 | if (type > RTM_MAX) | 1921 | if (type > RTM_MAX) |
1922 | return -EOPNOTSUPP; | 1922 | return -EOPNOTSUPP; |
1923 | 1923 | ||
1924 | type -= RTM_BASE; | 1924 | type -= RTM_BASE; |
1925 | 1925 | ||
1926 | /* All the messages must have at least 1 byte length */ | 1926 | /* All the messages must have at least 1 byte length */ |
1927 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) | 1927 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) |
1928 | return 0; | 1928 | return 0; |
1929 | 1929 | ||
1930 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; | 1930 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; |
1931 | sz_idx = type>>2; | 1931 | sz_idx = type>>2; |
1932 | kind = type&3; | 1932 | kind = type&3; |
1933 | 1933 | ||
1934 | if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) | 1934 | if (kind != 2 && !capable(CAP_NET_ADMIN)) |
1935 | return -EPERM; | 1935 | return -EPERM; |
1936 | 1936 | ||
1937 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { | 1937 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { |
1938 | struct sock *rtnl; | 1938 | struct sock *rtnl; |
1939 | rtnl_dumpit_func dumpit; | 1939 | rtnl_dumpit_func dumpit; |
1940 | rtnl_calcit_func calcit; | 1940 | rtnl_calcit_func calcit; |
1941 | u16 min_dump_alloc = 0; | 1941 | u16 min_dump_alloc = 0; |
1942 | 1942 | ||
1943 | dumpit = rtnl_get_dumpit(family, type); | 1943 | dumpit = rtnl_get_dumpit(family, type); |
1944 | if (dumpit == NULL) | 1944 | if (dumpit == NULL) |
1945 | return -EOPNOTSUPP; | 1945 | return -EOPNOTSUPP; |
1946 | calcit = rtnl_get_calcit(family, type); | 1946 | calcit = rtnl_get_calcit(family, type); |
1947 | if (calcit) | 1947 | if (calcit) |
1948 | min_dump_alloc = calcit(skb); | 1948 | min_dump_alloc = calcit(skb); |
1949 | 1949 | ||
1950 | __rtnl_unlock(); | 1950 | __rtnl_unlock(); |
1951 | rtnl = net->rtnl; | 1951 | rtnl = net->rtnl; |
1952 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, | 1952 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, |
1953 | NULL, min_dump_alloc); | 1953 | NULL, min_dump_alloc); |
1954 | rtnl_lock(); | 1954 | rtnl_lock(); |
1955 | return err; | 1955 | return err; |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); | 1958 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); |
1959 | 1959 | ||
1960 | min_len = rtm_min[sz_idx]; | 1960 | min_len = rtm_min[sz_idx]; |
1961 | if (nlh->nlmsg_len < min_len) | 1961 | if (nlh->nlmsg_len < min_len) |
1962 | return -EINVAL; | 1962 | return -EINVAL; |
1963 | 1963 | ||
1964 | if (nlh->nlmsg_len > min_len) { | 1964 | if (nlh->nlmsg_len > min_len) { |
1965 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | 1965 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); |
1966 | struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); | 1966 | struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); |
1967 | 1967 | ||
1968 | while (RTA_OK(attr, attrlen)) { | 1968 | while (RTA_OK(attr, attrlen)) { |
1969 | unsigned flavor = attr->rta_type; | 1969 | unsigned flavor = attr->rta_type; |
1970 | if (flavor) { | 1970 | if (flavor) { |
1971 | if (flavor > rta_max[sz_idx]) | 1971 | if (flavor > rta_max[sz_idx]) |
1972 | return -EINVAL; | 1972 | return -EINVAL; |
1973 | rta_buf[flavor-1] = attr; | 1973 | rta_buf[flavor-1] = attr; |
1974 | } | 1974 | } |
1975 | attr = RTA_NEXT(attr, attrlen); | 1975 | attr = RTA_NEXT(attr, attrlen); |
1976 | } | 1976 | } |
1977 | } | 1977 | } |
1978 | 1978 | ||
1979 | doit = rtnl_get_doit(family, type); | 1979 | doit = rtnl_get_doit(family, type); |
1980 | if (doit == NULL) | 1980 | if (doit == NULL) |
1981 | return -EOPNOTSUPP; | 1981 | return -EOPNOTSUPP; |
1982 | 1982 | ||
1983 | return doit(skb, nlh, (void *)&rta_buf[0]); | 1983 | return doit(skb, nlh, (void *)&rta_buf[0]); |
1984 | } | 1984 | } |
1985 | 1985 | ||
1986 | static void rtnetlink_rcv(struct sk_buff *skb) | 1986 | static void rtnetlink_rcv(struct sk_buff *skb) |
1987 | { | 1987 | { |
1988 | rtnl_lock(); | 1988 | rtnl_lock(); |
1989 | netlink_rcv_skb(skb, &rtnetlink_rcv_msg); | 1989 | netlink_rcv_skb(skb, &rtnetlink_rcv_msg); |
1990 | rtnl_unlock(); | 1990 | rtnl_unlock(); |
1991 | } | 1991 | } |
1992 | 1992 | ||
1993 | static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) | 1993 | static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) |
1994 | { | 1994 | { |
1995 | struct net_device *dev = ptr; | 1995 | struct net_device *dev = ptr; |
1996 | 1996 | ||
1997 | switch (event) { | 1997 | switch (event) { |
1998 | case NETDEV_UP: | 1998 | case NETDEV_UP: |
1999 | case NETDEV_DOWN: | 1999 | case NETDEV_DOWN: |
2000 | case NETDEV_PRE_UP: | 2000 | case NETDEV_PRE_UP: |
2001 | case NETDEV_POST_INIT: | 2001 | case NETDEV_POST_INIT: |
2002 | case NETDEV_REGISTER: | 2002 | case NETDEV_REGISTER: |
2003 | case NETDEV_CHANGE: | 2003 | case NETDEV_CHANGE: |
2004 | case NETDEV_PRE_TYPE_CHANGE: | 2004 | case NETDEV_PRE_TYPE_CHANGE: |
2005 | case NETDEV_GOING_DOWN: | 2005 | case NETDEV_GOING_DOWN: |
2006 | case NETDEV_UNREGISTER: | 2006 | case NETDEV_UNREGISTER: |
2007 | case NETDEV_UNREGISTER_BATCH: | 2007 | case NETDEV_UNREGISTER_BATCH: |
2008 | case NETDEV_RELEASE: | 2008 | case NETDEV_RELEASE: |
2009 | case NETDEV_JOIN: | 2009 | case NETDEV_JOIN: |
2010 | break; | 2010 | break; |
2011 | default: | 2011 | default: |
2012 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); | 2012 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); |
2013 | break; | 2013 | break; |
2014 | } | 2014 | } |
2015 | return NOTIFY_DONE; | 2015 | return NOTIFY_DONE; |
2016 | } | 2016 | } |
2017 | 2017 | ||
2018 | static struct notifier_block rtnetlink_dev_notifier = { | 2018 | static struct notifier_block rtnetlink_dev_notifier = { |
2019 | .notifier_call = rtnetlink_event, | 2019 | .notifier_call = rtnetlink_event, |
2020 | }; | 2020 | }; |
2021 | 2021 | ||
2022 | 2022 | ||
2023 | static int __net_init rtnetlink_net_init(struct net *net) | 2023 | static int __net_init rtnetlink_net_init(struct net *net) |
2024 | { | 2024 | { |
2025 | struct sock *sk; | 2025 | struct sock *sk; |
2026 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, | 2026 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, |
2027 | rtnetlink_rcv, &rtnl_mutex, THIS_MODULE); | 2027 | rtnetlink_rcv, &rtnl_mutex, THIS_MODULE); |
2028 | if (!sk) | 2028 | if (!sk) |
2029 | return -ENOMEM; | 2029 | return -ENOMEM; |
2030 | net->rtnl = sk; | 2030 | net->rtnl = sk; |
2031 | return 0; | 2031 | return 0; |
2032 | } | 2032 | } |
2033 | 2033 | ||
2034 | static void __net_exit rtnetlink_net_exit(struct net *net) | 2034 | static void __net_exit rtnetlink_net_exit(struct net *net) |
2035 | { | 2035 | { |
2036 | netlink_kernel_release(net->rtnl); | 2036 | netlink_kernel_release(net->rtnl); |
2037 | net->rtnl = NULL; | 2037 | net->rtnl = NULL; |
2038 | } | 2038 | } |
2039 | 2039 | ||
2040 | static struct pernet_operations rtnetlink_net_ops = { | 2040 | static struct pernet_operations rtnetlink_net_ops = { |
2041 | .init = rtnetlink_net_init, | 2041 | .init = rtnetlink_net_init, |
2042 | .exit = rtnetlink_net_exit, | 2042 | .exit = rtnetlink_net_exit, |
2043 | }; | 2043 | }; |
2044 | 2044 | ||
2045 | void __init rtnetlink_init(void) | 2045 | void __init rtnetlink_init(void) |
2046 | { | 2046 | { |
2047 | int i; | 2047 | int i; |
2048 | 2048 | ||
2049 | rtattr_max = 0; | 2049 | rtattr_max = 0; |
2050 | for (i = 0; i < ARRAY_SIZE(rta_max); i++) | 2050 | for (i = 0; i < ARRAY_SIZE(rta_max); i++) |
2051 | if (rta_max[i] > rtattr_max) | 2051 | if (rta_max[i] > rtattr_max) |
2052 | rtattr_max = rta_max[i]; | 2052 | rtattr_max = rta_max[i]; |
2053 | rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL); | 2053 | rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL); |
2054 | if (!rta_buf) | 2054 | if (!rta_buf) |
2055 | panic("rtnetlink_init: cannot allocate rta_buf\n"); | 2055 | panic("rtnetlink_init: cannot allocate rta_buf\n"); |
2056 | 2056 | ||
2057 | if (register_pernet_subsys(&rtnetlink_net_ops)) | 2057 | if (register_pernet_subsys(&rtnetlink_net_ops)) |
2058 | panic("rtnetlink_init: cannot initialize rtnetlink\n"); | 2058 | panic("rtnetlink_init: cannot initialize rtnetlink\n"); |
2059 | 2059 | ||
2060 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); | 2060 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); |
2061 | register_netdevice_notifier(&rtnetlink_dev_notifier); | 2061 | register_netdevice_notifier(&rtnetlink_dev_notifier); |
2062 | 2062 | ||
2063 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, | 2063 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, |
2064 | rtnl_dump_ifinfo, rtnl_calcit); | 2064 | rtnl_dump_ifinfo, rtnl_calcit); |
2065 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL); | 2065 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL); |
2066 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL); | 2066 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL); |
2067 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL); | 2067 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL); |
2068 | 2068 | ||
2069 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); | 2069 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); |
2070 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); | 2070 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | 2073 |
net/decnet/netfilter/dn_rtmsg.c
1 | /* | 1 | /* |
2 | * DECnet An implementation of the DECnet protocol suite for the LINUX | 2 | * DECnet An implementation of the DECnet protocol suite for the LINUX |
3 | * operating system. DECnet is implemented using the BSD Socket | 3 | * operating system. DECnet is implemented using the BSD Socket |
4 | * interface as the means of communication with the user level. | 4 | * interface as the means of communication with the user level. |
5 | * | 5 | * |
6 | * DECnet Routing Message Grabulator | 6 | * DECnet Routing Message Grabulator |
7 | * | 7 | * |
8 | * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/ | 8 | * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/ |
9 | * This code may be copied under the GPL v.2 or at your option | 9 | * This code may be copied under the GPL v.2 or at your option |
10 | * any later version. | 10 | * any later version. |
11 | * | 11 | * |
12 | * Author: Steven Whitehouse <steve@chygwyn.com> | 12 | * Author: Steven Whitehouse <steve@chygwyn.com> |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/netfilter.h> | 20 | #include <linux/netfilter.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/netlink.h> | 22 | #include <linux/netlink.h> |
23 | #include <linux/netfilter_decnet.h> | 23 | #include <linux/netfilter_decnet.h> |
24 | 24 | ||
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <net/flow.h> | 26 | #include <net/flow.h> |
27 | #include <net/dn.h> | 27 | #include <net/dn.h> |
28 | #include <net/dn_route.h> | 28 | #include <net/dn_route.h> |
29 | 29 | ||
30 | static struct sock *dnrmg = NULL; | 30 | static struct sock *dnrmg = NULL; |
31 | 31 | ||
32 | 32 | ||
33 | static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp) | 33 | static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp) |
34 | { | 34 | { |
35 | struct sk_buff *skb = NULL; | 35 | struct sk_buff *skb = NULL; |
36 | size_t size; | 36 | size_t size; |
37 | sk_buff_data_t old_tail; | 37 | sk_buff_data_t old_tail; |
38 | struct nlmsghdr *nlh; | 38 | struct nlmsghdr *nlh; |
39 | unsigned char *ptr; | 39 | unsigned char *ptr; |
40 | struct nf_dn_rtmsg *rtm; | 40 | struct nf_dn_rtmsg *rtm; |
41 | 41 | ||
42 | size = NLMSG_SPACE(rt_skb->len); | 42 | size = NLMSG_SPACE(rt_skb->len); |
43 | size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)); | 43 | size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)); |
44 | skb = alloc_skb(size, GFP_ATOMIC); | 44 | skb = alloc_skb(size, GFP_ATOMIC); |
45 | if (!skb) | 45 | if (!skb) |
46 | goto nlmsg_failure; | 46 | goto nlmsg_failure; |
47 | old_tail = skb->tail; | 47 | old_tail = skb->tail; |
48 | nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh)); | 48 | nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh)); |
49 | rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh); | 49 | rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh); |
50 | rtm->nfdn_ifindex = rt_skb->dev->ifindex; | 50 | rtm->nfdn_ifindex = rt_skb->dev->ifindex; |
51 | ptr = NFDN_RTMSG(rtm); | 51 | ptr = NFDN_RTMSG(rtm); |
52 | skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len); | 52 | skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len); |
53 | nlh->nlmsg_len = skb->tail - old_tail; | 53 | nlh->nlmsg_len = skb->tail - old_tail; |
54 | return skb; | 54 | return skb; |
55 | 55 | ||
56 | nlmsg_failure: | 56 | nlmsg_failure: |
57 | if (skb) | 57 | if (skb) |
58 | kfree_skb(skb); | 58 | kfree_skb(skb); |
59 | *errp = -ENOMEM; | 59 | *errp = -ENOMEM; |
60 | if (net_ratelimit()) | 60 | if (net_ratelimit()) |
61 | printk(KERN_ERR "dn_rtmsg: error creating netlink message\n"); | 61 | printk(KERN_ERR "dn_rtmsg: error creating netlink message\n"); |
62 | return NULL; | 62 | return NULL; |
63 | } | 63 | } |
64 | 64 | ||
65 | static void dnrmg_send_peer(struct sk_buff *skb) | 65 | static void dnrmg_send_peer(struct sk_buff *skb) |
66 | { | 66 | { |
67 | struct sk_buff *skb2; | 67 | struct sk_buff *skb2; |
68 | int status = 0; | 68 | int status = 0; |
69 | int group = 0; | 69 | int group = 0; |
70 | unsigned char flags = *skb->data; | 70 | unsigned char flags = *skb->data; |
71 | 71 | ||
72 | switch (flags & DN_RT_CNTL_MSK) { | 72 | switch (flags & DN_RT_CNTL_MSK) { |
73 | case DN_RT_PKT_L1RT: | 73 | case DN_RT_PKT_L1RT: |
74 | group = DNRNG_NLGRP_L1; | 74 | group = DNRNG_NLGRP_L1; |
75 | break; | 75 | break; |
76 | case DN_RT_PKT_L2RT: | 76 | case DN_RT_PKT_L2RT: |
77 | group = DNRNG_NLGRP_L2; | 77 | group = DNRNG_NLGRP_L2; |
78 | break; | 78 | break; |
79 | default: | 79 | default: |
80 | return; | 80 | return; |
81 | } | 81 | } |
82 | 82 | ||
83 | skb2 = dnrmg_build_message(skb, &status); | 83 | skb2 = dnrmg_build_message(skb, &status); |
84 | if (skb2 == NULL) | 84 | if (skb2 == NULL) |
85 | return; | 85 | return; |
86 | NETLINK_CB(skb2).dst_group = group; | 86 | NETLINK_CB(skb2).dst_group = group; |
87 | netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC); | 87 | netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC); |
88 | } | 88 | } |
89 | 89 | ||
90 | 90 | ||
91 | static unsigned int dnrmg_hook(unsigned int hook, | 91 | static unsigned int dnrmg_hook(unsigned int hook, |
92 | struct sk_buff *skb, | 92 | struct sk_buff *skb, |
93 | const struct net_device *in, | 93 | const struct net_device *in, |
94 | const struct net_device *out, | 94 | const struct net_device *out, |
95 | int (*okfn)(struct sk_buff *)) | 95 | int (*okfn)(struct sk_buff *)) |
96 | { | 96 | { |
97 | dnrmg_send_peer(skb); | 97 | dnrmg_send_peer(skb); |
98 | return NF_ACCEPT; | 98 | return NF_ACCEPT; |
99 | } | 99 | } |
100 | 100 | ||
101 | 101 | ||
102 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) | 102 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
103 | 103 | ||
104 | static inline void dnrmg_receive_user_skb(struct sk_buff *skb) | 104 | static inline void dnrmg_receive_user_skb(struct sk_buff *skb) |
105 | { | 105 | { |
106 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | 106 | struct nlmsghdr *nlh = nlmsg_hdr(skb); |
107 | 107 | ||
108 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) | 108 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) |
109 | return; | 109 | return; |
110 | 110 | ||
111 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 111 | if (!capable(CAP_NET_ADMIN)) |
112 | RCV_SKB_FAIL(-EPERM); | 112 | RCV_SKB_FAIL(-EPERM); |
113 | 113 | ||
114 | /* Eventually we might send routing messages too */ | 114 | /* Eventually we might send routing messages too */ |
115 | 115 | ||
116 | RCV_SKB_FAIL(-EINVAL); | 116 | RCV_SKB_FAIL(-EINVAL); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct nf_hook_ops dnrmg_ops __read_mostly = { | 119 | static struct nf_hook_ops dnrmg_ops __read_mostly = { |
120 | .hook = dnrmg_hook, | 120 | .hook = dnrmg_hook, |
121 | .pf = PF_DECnet, | 121 | .pf = PF_DECnet, |
122 | .hooknum = NF_DN_ROUTE, | 122 | .hooknum = NF_DN_ROUTE, |
123 | .priority = NF_DN_PRI_DNRTMSG, | 123 | .priority = NF_DN_PRI_DNRTMSG, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static int __init dn_rtmsg_init(void) | 126 | static int __init dn_rtmsg_init(void) |
127 | { | 127 | { |
128 | int rv = 0; | 128 | int rv = 0; |
129 | 129 | ||
130 | dnrmg = netlink_kernel_create(&init_net, | 130 | dnrmg = netlink_kernel_create(&init_net, |
131 | NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, | 131 | NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, |
132 | dnrmg_receive_user_skb, | 132 | dnrmg_receive_user_skb, |
133 | NULL, THIS_MODULE); | 133 | NULL, THIS_MODULE); |
134 | if (dnrmg == NULL) { | 134 | if (dnrmg == NULL) { |
135 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); | 135 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); |
136 | return -ENOMEM; | 136 | return -ENOMEM; |
137 | } | 137 | } |
138 | 138 | ||
139 | rv = nf_register_hook(&dnrmg_ops); | 139 | rv = nf_register_hook(&dnrmg_ops); |
140 | if (rv) { | 140 | if (rv) { |
141 | netlink_kernel_release(dnrmg); | 141 | netlink_kernel_release(dnrmg); |
142 | } | 142 | } |
143 | 143 | ||
144 | return rv; | 144 | return rv; |
145 | } | 145 | } |
146 | 146 | ||
147 | static void __exit dn_rtmsg_fini(void) | 147 | static void __exit dn_rtmsg_fini(void) |
148 | { | 148 | { |
149 | nf_unregister_hook(&dnrmg_ops); | 149 | nf_unregister_hook(&dnrmg_ops); |
150 | netlink_kernel_release(dnrmg); | 150 | netlink_kernel_release(dnrmg); |
151 | } | 151 | } |
152 | 152 | ||
153 | 153 | ||
154 | MODULE_DESCRIPTION("DECnet Routing Message Grabulator"); | 154 | MODULE_DESCRIPTION("DECnet Routing Message Grabulator"); |
155 | MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>"); | 155 | MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>"); |
156 | MODULE_LICENSE("GPL"); | 156 | MODULE_LICENSE("GPL"); |
157 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG); | 157 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG); |
158 | 158 | ||
159 | module_init(dn_rtmsg_init); | 159 | module_init(dn_rtmsg_init); |
160 | module_exit(dn_rtmsg_fini); | 160 | module_exit(dn_rtmsg_fini); |
161 | 161 | ||
162 | 162 |
net/ipv4/netfilter/ip_queue.c
1 | /* | 1 | /* |
2 | * This is a module which is used for queueing IPv4 packets and | 2 | * This is a module which is used for queueing IPv4 packets and |
3 | * communicating with userspace via netlink. | 3 | * communicating with userspace via netlink. |
4 | * | 4 | * |
5 | * (C) 2000-2002 James Morris <jmorris@intercode.com.au> | 5 | * (C) 2000-2002 James Morris <jmorris@intercode.com.au> |
6 | * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org> | 6 | * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
16 | #include <linux/notifier.h> | 16 | #include <linux/notifier.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/netfilter.h> | 18 | #include <linux/netfilter.h> |
19 | #include <linux/netfilter_ipv4/ip_queue.h> | 19 | #include <linux/netfilter_ipv4/ip_queue.h> |
20 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
21 | #include <linux/netlink.h> | 21 | #include <linux/netlink.h> |
22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/sysctl.h> | 23 | #include <linux/sysctl.h> |
24 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
27 | #include <linux/net.h> | 27 | #include <linux/net.h> |
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <net/net_namespace.h> | 30 | #include <net/net_namespace.h> |
31 | #include <net/sock.h> | 31 | #include <net/sock.h> |
32 | #include <net/route.h> | 32 | #include <net/route.h> |
33 | #include <net/netfilter/nf_queue.h> | 33 | #include <net/netfilter/nf_queue.h> |
34 | #include <net/ip.h> | 34 | #include <net/ip.h> |
35 | 35 | ||
36 | #define IPQ_QMAX_DEFAULT 1024 | 36 | #define IPQ_QMAX_DEFAULT 1024 |
37 | #define IPQ_PROC_FS_NAME "ip_queue" | 37 | #define IPQ_PROC_FS_NAME "ip_queue" |
38 | #define NET_IPQ_QMAX 2088 | 38 | #define NET_IPQ_QMAX 2088 |
39 | #define NET_IPQ_QMAX_NAME "ip_queue_maxlen" | 39 | #define NET_IPQ_QMAX_NAME "ip_queue_maxlen" |
40 | 40 | ||
41 | typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); | 41 | typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); |
42 | 42 | ||
43 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; | 43 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; |
44 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; | 44 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; |
45 | static DEFINE_SPINLOCK(queue_lock); | 45 | static DEFINE_SPINLOCK(queue_lock); |
46 | static int peer_pid __read_mostly; | 46 | static int peer_pid __read_mostly; |
47 | static unsigned int copy_range __read_mostly; | 47 | static unsigned int copy_range __read_mostly; |
48 | static unsigned int queue_total; | 48 | static unsigned int queue_total; |
49 | static unsigned int queue_dropped = 0; | 49 | static unsigned int queue_dropped = 0; |
50 | static unsigned int queue_user_dropped = 0; | 50 | static unsigned int queue_user_dropped = 0; |
51 | static struct sock *ipqnl __read_mostly; | 51 | static struct sock *ipqnl __read_mostly; |
52 | static LIST_HEAD(queue_list); | 52 | static LIST_HEAD(queue_list); |
53 | static DEFINE_MUTEX(ipqnl_mutex); | 53 | static DEFINE_MUTEX(ipqnl_mutex); |
54 | 54 | ||
55 | static inline void | 55 | static inline void |
56 | __ipq_enqueue_entry(struct nf_queue_entry *entry) | 56 | __ipq_enqueue_entry(struct nf_queue_entry *entry) |
57 | { | 57 | { |
58 | list_add_tail(&entry->list, &queue_list); | 58 | list_add_tail(&entry->list, &queue_list); |
59 | queue_total++; | 59 | queue_total++; |
60 | } | 60 | } |
61 | 61 | ||
62 | static inline int | 62 | static inline int |
63 | __ipq_set_mode(unsigned char mode, unsigned int range) | 63 | __ipq_set_mode(unsigned char mode, unsigned int range) |
64 | { | 64 | { |
65 | int status = 0; | 65 | int status = 0; |
66 | 66 | ||
67 | switch(mode) { | 67 | switch(mode) { |
68 | case IPQ_COPY_NONE: | 68 | case IPQ_COPY_NONE: |
69 | case IPQ_COPY_META: | 69 | case IPQ_COPY_META: |
70 | copy_mode = mode; | 70 | copy_mode = mode; |
71 | copy_range = 0; | 71 | copy_range = 0; |
72 | break; | 72 | break; |
73 | 73 | ||
74 | case IPQ_COPY_PACKET: | 74 | case IPQ_COPY_PACKET: |
75 | if (range > 0xFFFF) | 75 | if (range > 0xFFFF) |
76 | range = 0xFFFF; | 76 | range = 0xFFFF; |
77 | copy_range = range; | 77 | copy_range = range; |
78 | copy_mode = mode; | 78 | copy_mode = mode; |
79 | break; | 79 | break; |
80 | 80 | ||
81 | default: | 81 | default: |
82 | status = -EINVAL; | 82 | status = -EINVAL; |
83 | 83 | ||
84 | } | 84 | } |
85 | return status; | 85 | return status; |
86 | } | 86 | } |
87 | 87 | ||
88 | static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data); | 88 | static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data); |
89 | 89 | ||
90 | static inline void | 90 | static inline void |
91 | __ipq_reset(void) | 91 | __ipq_reset(void) |
92 | { | 92 | { |
93 | peer_pid = 0; | 93 | peer_pid = 0; |
94 | net_disable_timestamp(); | 94 | net_disable_timestamp(); |
95 | __ipq_set_mode(IPQ_COPY_NONE, 0); | 95 | __ipq_set_mode(IPQ_COPY_NONE, 0); |
96 | __ipq_flush(NULL, 0); | 96 | __ipq_flush(NULL, 0); |
97 | } | 97 | } |
98 | 98 | ||
99 | static struct nf_queue_entry * | 99 | static struct nf_queue_entry * |
100 | ipq_find_dequeue_entry(unsigned long id) | 100 | ipq_find_dequeue_entry(unsigned long id) |
101 | { | 101 | { |
102 | struct nf_queue_entry *entry = NULL, *i; | 102 | struct nf_queue_entry *entry = NULL, *i; |
103 | 103 | ||
104 | spin_lock_bh(&queue_lock); | 104 | spin_lock_bh(&queue_lock); |
105 | 105 | ||
106 | list_for_each_entry(i, &queue_list, list) { | 106 | list_for_each_entry(i, &queue_list, list) { |
107 | if ((unsigned long)i == id) { | 107 | if ((unsigned long)i == id) { |
108 | entry = i; | 108 | entry = i; |
109 | break; | 109 | break; |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | if (entry) { | 113 | if (entry) { |
114 | list_del(&entry->list); | 114 | list_del(&entry->list); |
115 | queue_total--; | 115 | queue_total--; |
116 | } | 116 | } |
117 | 117 | ||
118 | spin_unlock_bh(&queue_lock); | 118 | spin_unlock_bh(&queue_lock); |
119 | return entry; | 119 | return entry; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void | 122 | static void |
123 | __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 123 | __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
124 | { | 124 | { |
125 | struct nf_queue_entry *entry, *next; | 125 | struct nf_queue_entry *entry, *next; |
126 | 126 | ||
127 | list_for_each_entry_safe(entry, next, &queue_list, list) { | 127 | list_for_each_entry_safe(entry, next, &queue_list, list) { |
128 | if (!cmpfn || cmpfn(entry, data)) { | 128 | if (!cmpfn || cmpfn(entry, data)) { |
129 | list_del(&entry->list); | 129 | list_del(&entry->list); |
130 | queue_total--; | 130 | queue_total--; |
131 | nf_reinject(entry, NF_DROP); | 131 | nf_reinject(entry, NF_DROP); |
132 | } | 132 | } |
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | static void | 136 | static void |
137 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 137 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
138 | { | 138 | { |
139 | spin_lock_bh(&queue_lock); | 139 | spin_lock_bh(&queue_lock); |
140 | __ipq_flush(cmpfn, data); | 140 | __ipq_flush(cmpfn, data); |
141 | spin_unlock_bh(&queue_lock); | 141 | spin_unlock_bh(&queue_lock); |
142 | } | 142 | } |
143 | 143 | ||
144 | static struct sk_buff * | 144 | static struct sk_buff * |
145 | ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | 145 | ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) |
146 | { | 146 | { |
147 | sk_buff_data_t old_tail; | 147 | sk_buff_data_t old_tail; |
148 | size_t size = 0; | 148 | size_t size = 0; |
149 | size_t data_len = 0; | 149 | size_t data_len = 0; |
150 | struct sk_buff *skb; | 150 | struct sk_buff *skb; |
151 | struct ipq_packet_msg *pmsg; | 151 | struct ipq_packet_msg *pmsg; |
152 | struct nlmsghdr *nlh; | 152 | struct nlmsghdr *nlh; |
153 | struct timeval tv; | 153 | struct timeval tv; |
154 | 154 | ||
155 | switch (ACCESS_ONCE(copy_mode)) { | 155 | switch (ACCESS_ONCE(copy_mode)) { |
156 | case IPQ_COPY_META: | 156 | case IPQ_COPY_META: |
157 | case IPQ_COPY_NONE: | 157 | case IPQ_COPY_NONE: |
158 | size = NLMSG_SPACE(sizeof(*pmsg)); | 158 | size = NLMSG_SPACE(sizeof(*pmsg)); |
159 | break; | 159 | break; |
160 | 160 | ||
161 | case IPQ_COPY_PACKET: | 161 | case IPQ_COPY_PACKET: |
162 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && | 162 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
163 | (*errp = skb_checksum_help(entry->skb))) | 163 | (*errp = skb_checksum_help(entry->skb))) |
164 | return NULL; | 164 | return NULL; |
165 | 165 | ||
166 | data_len = ACCESS_ONCE(copy_range); | 166 | data_len = ACCESS_ONCE(copy_range); |
167 | if (data_len == 0 || data_len > entry->skb->len) | 167 | if (data_len == 0 || data_len > entry->skb->len) |
168 | data_len = entry->skb->len; | 168 | data_len = entry->skb->len; |
169 | 169 | ||
170 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); | 170 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); |
171 | break; | 171 | break; |
172 | 172 | ||
173 | default: | 173 | default: |
174 | *errp = -EINVAL; | 174 | *errp = -EINVAL; |
175 | return NULL; | 175 | return NULL; |
176 | } | 176 | } |
177 | 177 | ||
178 | skb = alloc_skb(size, GFP_ATOMIC); | 178 | skb = alloc_skb(size, GFP_ATOMIC); |
179 | if (!skb) | 179 | if (!skb) |
180 | goto nlmsg_failure; | 180 | goto nlmsg_failure; |
181 | 181 | ||
182 | old_tail = skb->tail; | 182 | old_tail = skb->tail; |
183 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); | 183 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); |
184 | pmsg = NLMSG_DATA(nlh); | 184 | pmsg = NLMSG_DATA(nlh); |
185 | memset(pmsg, 0, sizeof(*pmsg)); | 185 | memset(pmsg, 0, sizeof(*pmsg)); |
186 | 186 | ||
187 | pmsg->packet_id = (unsigned long )entry; | 187 | pmsg->packet_id = (unsigned long )entry; |
188 | pmsg->data_len = data_len; | 188 | pmsg->data_len = data_len; |
189 | tv = ktime_to_timeval(entry->skb->tstamp); | 189 | tv = ktime_to_timeval(entry->skb->tstamp); |
190 | pmsg->timestamp_sec = tv.tv_sec; | 190 | pmsg->timestamp_sec = tv.tv_sec; |
191 | pmsg->timestamp_usec = tv.tv_usec; | 191 | pmsg->timestamp_usec = tv.tv_usec; |
192 | pmsg->mark = entry->skb->mark; | 192 | pmsg->mark = entry->skb->mark; |
193 | pmsg->hook = entry->hook; | 193 | pmsg->hook = entry->hook; |
194 | pmsg->hw_protocol = entry->skb->protocol; | 194 | pmsg->hw_protocol = entry->skb->protocol; |
195 | 195 | ||
196 | if (entry->indev) | 196 | if (entry->indev) |
197 | strcpy(pmsg->indev_name, entry->indev->name); | 197 | strcpy(pmsg->indev_name, entry->indev->name); |
198 | else | 198 | else |
199 | pmsg->indev_name[0] = '\0'; | 199 | pmsg->indev_name[0] = '\0'; |
200 | 200 | ||
201 | if (entry->outdev) | 201 | if (entry->outdev) |
202 | strcpy(pmsg->outdev_name, entry->outdev->name); | 202 | strcpy(pmsg->outdev_name, entry->outdev->name); |
203 | else | 203 | else |
204 | pmsg->outdev_name[0] = '\0'; | 204 | pmsg->outdev_name[0] = '\0'; |
205 | 205 | ||
206 | if (entry->indev && entry->skb->dev && | 206 | if (entry->indev && entry->skb->dev && |
207 | entry->skb->mac_header != entry->skb->network_header) { | 207 | entry->skb->mac_header != entry->skb->network_header) { |
208 | pmsg->hw_type = entry->skb->dev->type; | 208 | pmsg->hw_type = entry->skb->dev->type; |
209 | pmsg->hw_addrlen = dev_parse_header(entry->skb, | 209 | pmsg->hw_addrlen = dev_parse_header(entry->skb, |
210 | pmsg->hw_addr); | 210 | pmsg->hw_addr); |
211 | } | 211 | } |
212 | 212 | ||
213 | if (data_len) | 213 | if (data_len) |
214 | if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len)) | 214 | if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len)) |
215 | BUG(); | 215 | BUG(); |
216 | 216 | ||
217 | nlh->nlmsg_len = skb->tail - old_tail; | 217 | nlh->nlmsg_len = skb->tail - old_tail; |
218 | return skb; | 218 | return skb; |
219 | 219 | ||
220 | nlmsg_failure: | 220 | nlmsg_failure: |
221 | kfree_skb(skb); | 221 | kfree_skb(skb); |
222 | *errp = -EINVAL; | 222 | *errp = -EINVAL; |
223 | printk(KERN_ERR "ip_queue: error creating packet message\n"); | 223 | printk(KERN_ERR "ip_queue: error creating packet message\n"); |
224 | return NULL; | 224 | return NULL; |
225 | } | 225 | } |
226 | 226 | ||
227 | static int | 227 | static int |
228 | ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | 228 | ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) |
229 | { | 229 | { |
230 | int status = -EINVAL; | 230 | int status = -EINVAL; |
231 | struct sk_buff *nskb; | 231 | struct sk_buff *nskb; |
232 | 232 | ||
233 | if (copy_mode == IPQ_COPY_NONE) | 233 | if (copy_mode == IPQ_COPY_NONE) |
234 | return -EAGAIN; | 234 | return -EAGAIN; |
235 | 235 | ||
236 | nskb = ipq_build_packet_message(entry, &status); | 236 | nskb = ipq_build_packet_message(entry, &status); |
237 | if (nskb == NULL) | 237 | if (nskb == NULL) |
238 | return status; | 238 | return status; |
239 | 239 | ||
240 | spin_lock_bh(&queue_lock); | 240 | spin_lock_bh(&queue_lock); |
241 | 241 | ||
242 | if (!peer_pid) | 242 | if (!peer_pid) |
243 | goto err_out_free_nskb; | 243 | goto err_out_free_nskb; |
244 | 244 | ||
245 | if (queue_total >= queue_maxlen) { | 245 | if (queue_total >= queue_maxlen) { |
246 | queue_dropped++; | 246 | queue_dropped++; |
247 | status = -ENOSPC; | 247 | status = -ENOSPC; |
248 | if (net_ratelimit()) | 248 | if (net_ratelimit()) |
249 | printk (KERN_WARNING "ip_queue: full at %d entries, " | 249 | printk (KERN_WARNING "ip_queue: full at %d entries, " |
250 | "dropping packets(s). Dropped: %d\n", queue_total, | 250 | "dropping packets(s). Dropped: %d\n", queue_total, |
251 | queue_dropped); | 251 | queue_dropped); |
252 | goto err_out_free_nskb; | 252 | goto err_out_free_nskb; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* netlink_unicast will either free the nskb or attach it to a socket */ | 255 | /* netlink_unicast will either free the nskb or attach it to a socket */ |
256 | status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); | 256 | status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); |
257 | if (status < 0) { | 257 | if (status < 0) { |
258 | queue_user_dropped++; | 258 | queue_user_dropped++; |
259 | goto err_out_unlock; | 259 | goto err_out_unlock; |
260 | } | 260 | } |
261 | 261 | ||
262 | __ipq_enqueue_entry(entry); | 262 | __ipq_enqueue_entry(entry); |
263 | 263 | ||
264 | spin_unlock_bh(&queue_lock); | 264 | spin_unlock_bh(&queue_lock); |
265 | return status; | 265 | return status; |
266 | 266 | ||
267 | err_out_free_nskb: | 267 | err_out_free_nskb: |
268 | kfree_skb(nskb); | 268 | kfree_skb(nskb); |
269 | 269 | ||
270 | err_out_unlock: | 270 | err_out_unlock: |
271 | spin_unlock_bh(&queue_lock); | 271 | spin_unlock_bh(&queue_lock); |
272 | return status; | 272 | return status; |
273 | } | 273 | } |
274 | 274 | ||
275 | static int | 275 | static int |
276 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e) | 276 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e) |
277 | { | 277 | { |
278 | int diff; | 278 | int diff; |
279 | struct iphdr *user_iph = (struct iphdr *)v->payload; | 279 | struct iphdr *user_iph = (struct iphdr *)v->payload; |
280 | struct sk_buff *nskb; | 280 | struct sk_buff *nskb; |
281 | 281 | ||
282 | if (v->data_len < sizeof(*user_iph)) | 282 | if (v->data_len < sizeof(*user_iph)) |
283 | return 0; | 283 | return 0; |
284 | diff = v->data_len - e->skb->len; | 284 | diff = v->data_len - e->skb->len; |
285 | if (diff < 0) { | 285 | if (diff < 0) { |
286 | if (pskb_trim(e->skb, v->data_len)) | 286 | if (pskb_trim(e->skb, v->data_len)) |
287 | return -ENOMEM; | 287 | return -ENOMEM; |
288 | } else if (diff > 0) { | 288 | } else if (diff > 0) { |
289 | if (v->data_len > 0xFFFF) | 289 | if (v->data_len > 0xFFFF) |
290 | return -EINVAL; | 290 | return -EINVAL; |
291 | if (diff > skb_tailroom(e->skb)) { | 291 | if (diff > skb_tailroom(e->skb)) { |
292 | nskb = skb_copy_expand(e->skb, skb_headroom(e->skb), | 292 | nskb = skb_copy_expand(e->skb, skb_headroom(e->skb), |
293 | diff, GFP_ATOMIC); | 293 | diff, GFP_ATOMIC); |
294 | if (!nskb) { | 294 | if (!nskb) { |
295 | printk(KERN_WARNING "ip_queue: error " | 295 | printk(KERN_WARNING "ip_queue: error " |
296 | "in mangle, dropping packet\n"); | 296 | "in mangle, dropping packet\n"); |
297 | return -ENOMEM; | 297 | return -ENOMEM; |
298 | } | 298 | } |
299 | kfree_skb(e->skb); | 299 | kfree_skb(e->skb); |
300 | e->skb = nskb; | 300 | e->skb = nskb; |
301 | } | 301 | } |
302 | skb_put(e->skb, diff); | 302 | skb_put(e->skb, diff); |
303 | } | 303 | } |
304 | if (!skb_make_writable(e->skb, v->data_len)) | 304 | if (!skb_make_writable(e->skb, v->data_len)) |
305 | return -ENOMEM; | 305 | return -ENOMEM; |
306 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 306 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
307 | e->skb->ip_summed = CHECKSUM_NONE; | 307 | e->skb->ip_summed = CHECKSUM_NONE; |
308 | 308 | ||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int | 312 | static int |
313 | ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) | 313 | ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) |
314 | { | 314 | { |
315 | struct nf_queue_entry *entry; | 315 | struct nf_queue_entry *entry; |
316 | 316 | ||
317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) | 317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) |
318 | return -EINVAL; | 318 | return -EINVAL; |
319 | 319 | ||
320 | entry = ipq_find_dequeue_entry(vmsg->id); | 320 | entry = ipq_find_dequeue_entry(vmsg->id); |
321 | if (entry == NULL) | 321 | if (entry == NULL) |
322 | return -ENOENT; | 322 | return -ENOENT; |
323 | else { | 323 | else { |
324 | int verdict = vmsg->value; | 324 | int verdict = vmsg->value; |
325 | 325 | ||
326 | if (vmsg->data_len && vmsg->data_len == len) | 326 | if (vmsg->data_len && vmsg->data_len == len) |
327 | if (ipq_mangle_ipv4(vmsg, entry) < 0) | 327 | if (ipq_mangle_ipv4(vmsg, entry) < 0) |
328 | verdict = NF_DROP; | 328 | verdict = NF_DROP; |
329 | 329 | ||
330 | nf_reinject(entry, verdict); | 330 | nf_reinject(entry, verdict); |
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | } | 333 | } |
334 | 334 | ||
335 | static int | 335 | static int |
336 | ipq_set_mode(unsigned char mode, unsigned int range) | 336 | ipq_set_mode(unsigned char mode, unsigned int range) |
337 | { | 337 | { |
338 | int status; | 338 | int status; |
339 | 339 | ||
340 | spin_lock_bh(&queue_lock); | 340 | spin_lock_bh(&queue_lock); |
341 | status = __ipq_set_mode(mode, range); | 341 | status = __ipq_set_mode(mode, range); |
342 | spin_unlock_bh(&queue_lock); | 342 | spin_unlock_bh(&queue_lock); |
343 | return status; | 343 | return status; |
344 | } | 344 | } |
345 | 345 | ||
346 | static int | 346 | static int |
347 | ipq_receive_peer(struct ipq_peer_msg *pmsg, | 347 | ipq_receive_peer(struct ipq_peer_msg *pmsg, |
348 | unsigned char type, unsigned int len) | 348 | unsigned char type, unsigned int len) |
349 | { | 349 | { |
350 | int status = 0; | 350 | int status = 0; |
351 | 351 | ||
352 | if (len < sizeof(*pmsg)) | 352 | if (len < sizeof(*pmsg)) |
353 | return -EINVAL; | 353 | return -EINVAL; |
354 | 354 | ||
355 | switch (type) { | 355 | switch (type) { |
356 | case IPQM_MODE: | 356 | case IPQM_MODE: |
357 | status = ipq_set_mode(pmsg->msg.mode.value, | 357 | status = ipq_set_mode(pmsg->msg.mode.value, |
358 | pmsg->msg.mode.range); | 358 | pmsg->msg.mode.range); |
359 | break; | 359 | break; |
360 | 360 | ||
361 | case IPQM_VERDICT: | 361 | case IPQM_VERDICT: |
362 | status = ipq_set_verdict(&pmsg->msg.verdict, | 362 | status = ipq_set_verdict(&pmsg->msg.verdict, |
363 | len - sizeof(*pmsg)); | 363 | len - sizeof(*pmsg)); |
364 | break; | 364 | break; |
365 | default: | 365 | default: |
366 | status = -EINVAL; | 366 | status = -EINVAL; |
367 | } | 367 | } |
368 | return status; | 368 | return status; |
369 | } | 369 | } |
370 | 370 | ||
371 | static int | 371 | static int |
372 | dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) | 372 | dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) |
373 | { | 373 | { |
374 | if (entry->indev) | 374 | if (entry->indev) |
375 | if (entry->indev->ifindex == ifindex) | 375 | if (entry->indev->ifindex == ifindex) |
376 | return 1; | 376 | return 1; |
377 | if (entry->outdev) | 377 | if (entry->outdev) |
378 | if (entry->outdev->ifindex == ifindex) | 378 | if (entry->outdev->ifindex == ifindex) |
379 | return 1; | 379 | return 1; |
380 | #ifdef CONFIG_BRIDGE_NETFILTER | 380 | #ifdef CONFIG_BRIDGE_NETFILTER |
381 | if (entry->skb->nf_bridge) { | 381 | if (entry->skb->nf_bridge) { |
382 | if (entry->skb->nf_bridge->physindev && | 382 | if (entry->skb->nf_bridge->physindev && |
383 | entry->skb->nf_bridge->physindev->ifindex == ifindex) | 383 | entry->skb->nf_bridge->physindev->ifindex == ifindex) |
384 | return 1; | 384 | return 1; |
385 | if (entry->skb->nf_bridge->physoutdev && | 385 | if (entry->skb->nf_bridge->physoutdev && |
386 | entry->skb->nf_bridge->physoutdev->ifindex == ifindex) | 386 | entry->skb->nf_bridge->physoutdev->ifindex == ifindex) |
387 | return 1; | 387 | return 1; |
388 | } | 388 | } |
389 | #endif | 389 | #endif |
390 | return 0; | 390 | return 0; |
391 | } | 391 | } |
392 | 392 | ||
393 | static void | 393 | static void |
394 | ipq_dev_drop(int ifindex) | 394 | ipq_dev_drop(int ifindex) |
395 | { | 395 | { |
396 | ipq_flush(dev_cmp, ifindex); | 396 | ipq_flush(dev_cmp, ifindex); |
397 | } | 397 | } |
398 | 398 | ||
399 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) | 399 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
400 | 400 | ||
401 | static inline void | 401 | static inline void |
402 | __ipq_rcv_skb(struct sk_buff *skb) | 402 | __ipq_rcv_skb(struct sk_buff *skb) |
403 | { | 403 | { |
404 | int status, type, pid, flags; | 404 | int status, type, pid, flags; |
405 | unsigned int nlmsglen, skblen; | 405 | unsigned int nlmsglen, skblen; |
406 | struct nlmsghdr *nlh; | 406 | struct nlmsghdr *nlh; |
407 | 407 | ||
408 | skblen = skb->len; | 408 | skblen = skb->len; |
409 | if (skblen < sizeof(*nlh)) | 409 | if (skblen < sizeof(*nlh)) |
410 | return; | 410 | return; |
411 | 411 | ||
412 | nlh = nlmsg_hdr(skb); | 412 | nlh = nlmsg_hdr(skb); |
413 | nlmsglen = nlh->nlmsg_len; | 413 | nlmsglen = nlh->nlmsg_len; |
414 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) | 414 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) |
415 | return; | 415 | return; |
416 | 416 | ||
417 | pid = nlh->nlmsg_pid; | 417 | pid = nlh->nlmsg_pid; |
418 | flags = nlh->nlmsg_flags; | 418 | flags = nlh->nlmsg_flags; |
419 | 419 | ||
420 | if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) | 420 | if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) |
421 | RCV_SKB_FAIL(-EINVAL); | 421 | RCV_SKB_FAIL(-EINVAL); |
422 | 422 | ||
423 | if (flags & MSG_TRUNC) | 423 | if (flags & MSG_TRUNC) |
424 | RCV_SKB_FAIL(-ECOMM); | 424 | RCV_SKB_FAIL(-ECOMM); |
425 | 425 | ||
426 | type = nlh->nlmsg_type; | 426 | type = nlh->nlmsg_type; |
427 | if (type < NLMSG_NOOP || type >= IPQM_MAX) | 427 | if (type < NLMSG_NOOP || type >= IPQM_MAX) |
428 | RCV_SKB_FAIL(-EINVAL); | 428 | RCV_SKB_FAIL(-EINVAL); |
429 | 429 | ||
430 | if (type <= IPQM_BASE) | 430 | if (type <= IPQM_BASE) |
431 | return; | 431 | return; |
432 | 432 | ||
433 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 433 | if (!capable(CAP_NET_ADMIN)) |
434 | RCV_SKB_FAIL(-EPERM); | 434 | RCV_SKB_FAIL(-EPERM); |
435 | 435 | ||
436 | spin_lock_bh(&queue_lock); | 436 | spin_lock_bh(&queue_lock); |
437 | 437 | ||
438 | if (peer_pid) { | 438 | if (peer_pid) { |
439 | if (peer_pid != pid) { | 439 | if (peer_pid != pid) { |
440 | spin_unlock_bh(&queue_lock); | 440 | spin_unlock_bh(&queue_lock); |
441 | RCV_SKB_FAIL(-EBUSY); | 441 | RCV_SKB_FAIL(-EBUSY); |
442 | } | 442 | } |
443 | } else { | 443 | } else { |
444 | net_enable_timestamp(); | 444 | net_enable_timestamp(); |
445 | peer_pid = pid; | 445 | peer_pid = pid; |
446 | } | 446 | } |
447 | 447 | ||
448 | spin_unlock_bh(&queue_lock); | 448 | spin_unlock_bh(&queue_lock); |
449 | 449 | ||
450 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 450 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
451 | nlmsglen - NLMSG_LENGTH(0)); | 451 | nlmsglen - NLMSG_LENGTH(0)); |
452 | if (status < 0) | 452 | if (status < 0) |
453 | RCV_SKB_FAIL(status); | 453 | RCV_SKB_FAIL(status); |
454 | 454 | ||
455 | if (flags & NLM_F_ACK) | 455 | if (flags & NLM_F_ACK) |
456 | netlink_ack(skb, nlh, 0); | 456 | netlink_ack(skb, nlh, 0); |
457 | } | 457 | } |
458 | 458 | ||
459 | static void | 459 | static void |
460 | ipq_rcv_skb(struct sk_buff *skb) | 460 | ipq_rcv_skb(struct sk_buff *skb) |
461 | { | 461 | { |
462 | mutex_lock(&ipqnl_mutex); | 462 | mutex_lock(&ipqnl_mutex); |
463 | __ipq_rcv_skb(skb); | 463 | __ipq_rcv_skb(skb); |
464 | mutex_unlock(&ipqnl_mutex); | 464 | mutex_unlock(&ipqnl_mutex); |
465 | } | 465 | } |
466 | 466 | ||
467 | static int | 467 | static int |
468 | ipq_rcv_dev_event(struct notifier_block *this, | 468 | ipq_rcv_dev_event(struct notifier_block *this, |
469 | unsigned long event, void *ptr) | 469 | unsigned long event, void *ptr) |
470 | { | 470 | { |
471 | struct net_device *dev = ptr; | 471 | struct net_device *dev = ptr; |
472 | 472 | ||
473 | if (!net_eq(dev_net(dev), &init_net)) | 473 | if (!net_eq(dev_net(dev), &init_net)) |
474 | return NOTIFY_DONE; | 474 | return NOTIFY_DONE; |
475 | 475 | ||
476 | /* Drop any packets associated with the downed device */ | 476 | /* Drop any packets associated with the downed device */ |
477 | if (event == NETDEV_DOWN) | 477 | if (event == NETDEV_DOWN) |
478 | ipq_dev_drop(dev->ifindex); | 478 | ipq_dev_drop(dev->ifindex); |
479 | return NOTIFY_DONE; | 479 | return NOTIFY_DONE; |
480 | } | 480 | } |
481 | 481 | ||
482 | static struct notifier_block ipq_dev_notifier = { | 482 | static struct notifier_block ipq_dev_notifier = { |
483 | .notifier_call = ipq_rcv_dev_event, | 483 | .notifier_call = ipq_rcv_dev_event, |
484 | }; | 484 | }; |
485 | 485 | ||
486 | static int | 486 | static int |
487 | ipq_rcv_nl_event(struct notifier_block *this, | 487 | ipq_rcv_nl_event(struct notifier_block *this, |
488 | unsigned long event, void *ptr) | 488 | unsigned long event, void *ptr) |
489 | { | 489 | { |
490 | struct netlink_notify *n = ptr; | 490 | struct netlink_notify *n = ptr; |
491 | 491 | ||
492 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_FIREWALL) { | 492 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_FIREWALL) { |
493 | spin_lock_bh(&queue_lock); | 493 | spin_lock_bh(&queue_lock); |
494 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 494 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
495 | __ipq_reset(); | 495 | __ipq_reset(); |
496 | spin_unlock_bh(&queue_lock); | 496 | spin_unlock_bh(&queue_lock); |
497 | } | 497 | } |
498 | return NOTIFY_DONE; | 498 | return NOTIFY_DONE; |
499 | } | 499 | } |
500 | 500 | ||
501 | static struct notifier_block ipq_nl_notifier = { | 501 | static struct notifier_block ipq_nl_notifier = { |
502 | .notifier_call = ipq_rcv_nl_event, | 502 | .notifier_call = ipq_rcv_nl_event, |
503 | }; | 503 | }; |
504 | 504 | ||
505 | #ifdef CONFIG_SYSCTL | 505 | #ifdef CONFIG_SYSCTL |
506 | static struct ctl_table_header *ipq_sysctl_header; | 506 | static struct ctl_table_header *ipq_sysctl_header; |
507 | 507 | ||
508 | static ctl_table ipq_table[] = { | 508 | static ctl_table ipq_table[] = { |
509 | { | 509 | { |
510 | .procname = NET_IPQ_QMAX_NAME, | 510 | .procname = NET_IPQ_QMAX_NAME, |
511 | .data = &queue_maxlen, | 511 | .data = &queue_maxlen, |
512 | .maxlen = sizeof(queue_maxlen), | 512 | .maxlen = sizeof(queue_maxlen), |
513 | .mode = 0644, | 513 | .mode = 0644, |
514 | .proc_handler = proc_dointvec | 514 | .proc_handler = proc_dointvec |
515 | }, | 515 | }, |
516 | { } | 516 | { } |
517 | }; | 517 | }; |
518 | #endif | 518 | #endif |
519 | 519 | ||
520 | #ifdef CONFIG_PROC_FS | 520 | #ifdef CONFIG_PROC_FS |
521 | static int ip_queue_show(struct seq_file *m, void *v) | 521 | static int ip_queue_show(struct seq_file *m, void *v) |
522 | { | 522 | { |
523 | spin_lock_bh(&queue_lock); | 523 | spin_lock_bh(&queue_lock); |
524 | 524 | ||
525 | seq_printf(m, | 525 | seq_printf(m, |
526 | "Peer PID : %d\n" | 526 | "Peer PID : %d\n" |
527 | "Copy mode : %hu\n" | 527 | "Copy mode : %hu\n" |
528 | "Copy range : %u\n" | 528 | "Copy range : %u\n" |
529 | "Queue length : %u\n" | 529 | "Queue length : %u\n" |
530 | "Queue max. length : %u\n" | 530 | "Queue max. length : %u\n" |
531 | "Queue dropped : %u\n" | 531 | "Queue dropped : %u\n" |
532 | "Netlink dropped : %u\n", | 532 | "Netlink dropped : %u\n", |
533 | peer_pid, | 533 | peer_pid, |
534 | copy_mode, | 534 | copy_mode, |
535 | copy_range, | 535 | copy_range, |
536 | queue_total, | 536 | queue_total, |
537 | queue_maxlen, | 537 | queue_maxlen, |
538 | queue_dropped, | 538 | queue_dropped, |
539 | queue_user_dropped); | 539 | queue_user_dropped); |
540 | 540 | ||
541 | spin_unlock_bh(&queue_lock); | 541 | spin_unlock_bh(&queue_lock); |
542 | return 0; | 542 | return 0; |
543 | } | 543 | } |
544 | 544 | ||
545 | static int ip_queue_open(struct inode *inode, struct file *file) | 545 | static int ip_queue_open(struct inode *inode, struct file *file) |
546 | { | 546 | { |
547 | return single_open(file, ip_queue_show, NULL); | 547 | return single_open(file, ip_queue_show, NULL); |
548 | } | 548 | } |
549 | 549 | ||
550 | static const struct file_operations ip_queue_proc_fops = { | 550 | static const struct file_operations ip_queue_proc_fops = { |
551 | .open = ip_queue_open, | 551 | .open = ip_queue_open, |
552 | .read = seq_read, | 552 | .read = seq_read, |
553 | .llseek = seq_lseek, | 553 | .llseek = seq_lseek, |
554 | .release = single_release, | 554 | .release = single_release, |
555 | .owner = THIS_MODULE, | 555 | .owner = THIS_MODULE, |
556 | }; | 556 | }; |
557 | #endif | 557 | #endif |
558 | 558 | ||
559 | static const struct nf_queue_handler nfqh = { | 559 | static const struct nf_queue_handler nfqh = { |
560 | .name = "ip_queue", | 560 | .name = "ip_queue", |
561 | .outfn = &ipq_enqueue_packet, | 561 | .outfn = &ipq_enqueue_packet, |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static int __init ip_queue_init(void) | 564 | static int __init ip_queue_init(void) |
565 | { | 565 | { |
566 | int status = -ENOMEM; | 566 | int status = -ENOMEM; |
567 | struct proc_dir_entry *proc __maybe_unused; | 567 | struct proc_dir_entry *proc __maybe_unused; |
568 | 568 | ||
569 | netlink_register_notifier(&ipq_nl_notifier); | 569 | netlink_register_notifier(&ipq_nl_notifier); |
570 | ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0, | 570 | ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0, |
571 | ipq_rcv_skb, NULL, THIS_MODULE); | 571 | ipq_rcv_skb, NULL, THIS_MODULE); |
572 | if (ipqnl == NULL) { | 572 | if (ipqnl == NULL) { |
573 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); | 573 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); |
574 | goto cleanup_netlink_notifier; | 574 | goto cleanup_netlink_notifier; |
575 | } | 575 | } |
576 | 576 | ||
577 | #ifdef CONFIG_PROC_FS | 577 | #ifdef CONFIG_PROC_FS |
578 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, | 578 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, |
579 | &ip_queue_proc_fops); | 579 | &ip_queue_proc_fops); |
580 | if (!proc) { | 580 | if (!proc) { |
581 | printk(KERN_ERR "ip_queue: failed to create proc entry\n"); | 581 | printk(KERN_ERR "ip_queue: failed to create proc entry\n"); |
582 | goto cleanup_ipqnl; | 582 | goto cleanup_ipqnl; |
583 | } | 583 | } |
584 | #endif | 584 | #endif |
585 | register_netdevice_notifier(&ipq_dev_notifier); | 585 | register_netdevice_notifier(&ipq_dev_notifier); |
586 | #ifdef CONFIG_SYSCTL | 586 | #ifdef CONFIG_SYSCTL |
587 | ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); | 587 | ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); |
588 | #endif | 588 | #endif |
589 | status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh); | 589 | status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh); |
590 | if (status < 0) { | 590 | if (status < 0) { |
591 | printk(KERN_ERR "ip_queue: failed to register queue handler\n"); | 591 | printk(KERN_ERR "ip_queue: failed to register queue handler\n"); |
592 | goto cleanup_sysctl; | 592 | goto cleanup_sysctl; |
593 | } | 593 | } |
594 | return status; | 594 | return status; |
595 | 595 | ||
596 | cleanup_sysctl: | 596 | cleanup_sysctl: |
597 | #ifdef CONFIG_SYSCTL | 597 | #ifdef CONFIG_SYSCTL |
598 | unregister_sysctl_table(ipq_sysctl_header); | 598 | unregister_sysctl_table(ipq_sysctl_header); |
599 | #endif | 599 | #endif |
600 | unregister_netdevice_notifier(&ipq_dev_notifier); | 600 | unregister_netdevice_notifier(&ipq_dev_notifier); |
601 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); | 601 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); |
602 | cleanup_ipqnl: __maybe_unused | 602 | cleanup_ipqnl: __maybe_unused |
603 | netlink_kernel_release(ipqnl); | 603 | netlink_kernel_release(ipqnl); |
604 | mutex_lock(&ipqnl_mutex); | 604 | mutex_lock(&ipqnl_mutex); |
605 | mutex_unlock(&ipqnl_mutex); | 605 | mutex_unlock(&ipqnl_mutex); |
606 | 606 | ||
607 | cleanup_netlink_notifier: | 607 | cleanup_netlink_notifier: |
608 | netlink_unregister_notifier(&ipq_nl_notifier); | 608 | netlink_unregister_notifier(&ipq_nl_notifier); |
609 | return status; | 609 | return status; |
610 | } | 610 | } |
611 | 611 | ||
612 | static void __exit ip_queue_fini(void) | 612 | static void __exit ip_queue_fini(void) |
613 | { | 613 | { |
614 | nf_unregister_queue_handlers(&nfqh); | 614 | nf_unregister_queue_handlers(&nfqh); |
615 | 615 | ||
616 | ipq_flush(NULL, 0); | 616 | ipq_flush(NULL, 0); |
617 | 617 | ||
618 | #ifdef CONFIG_SYSCTL | 618 | #ifdef CONFIG_SYSCTL |
619 | unregister_sysctl_table(ipq_sysctl_header); | 619 | unregister_sysctl_table(ipq_sysctl_header); |
620 | #endif | 620 | #endif |
621 | unregister_netdevice_notifier(&ipq_dev_notifier); | 621 | unregister_netdevice_notifier(&ipq_dev_notifier); |
622 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); | 622 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); |
623 | 623 | ||
624 | netlink_kernel_release(ipqnl); | 624 | netlink_kernel_release(ipqnl); |
625 | mutex_lock(&ipqnl_mutex); | 625 | mutex_lock(&ipqnl_mutex); |
626 | mutex_unlock(&ipqnl_mutex); | 626 | mutex_unlock(&ipqnl_mutex); |
627 | 627 | ||
628 | netlink_unregister_notifier(&ipq_nl_notifier); | 628 | netlink_unregister_notifier(&ipq_nl_notifier); |
629 | } | 629 | } |
630 | 630 | ||
631 | MODULE_DESCRIPTION("IPv4 packet queue handler"); | 631 | MODULE_DESCRIPTION("IPv4 packet queue handler"); |
632 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | 632 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); |
633 | MODULE_LICENSE("GPL"); | 633 | MODULE_LICENSE("GPL"); |
634 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_FIREWALL); | 634 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_FIREWALL); |
635 | 635 | ||
636 | module_init(ip_queue_init); | 636 | module_init(ip_queue_init); |
637 | module_exit(ip_queue_fini); | 637 | module_exit(ip_queue_fini); |
638 | 638 |
net/ipv6/netfilter/ip6_queue.c
1 | /* | 1 | /* |
2 | * This is a module which is used for queueing IPv6 packets and | 2 | * This is a module which is used for queueing IPv6 packets and |
3 | * communicating with userspace via netlink. | 3 | * communicating with userspace via netlink. |
4 | * | 4 | * |
5 | * (C) 2001 Fernando Anton, this code is GPL. | 5 | * (C) 2001 Fernando Anton, this code is GPL. |
6 | * IPv64 Project - Work based in IPv64 draft by Arturo Azcorra. | 6 | * IPv64 Project - Work based in IPv64 draft by Arturo Azcorra. |
7 | * Universidad Carlos III de Madrid - Leganes (Madrid) - Spain | 7 | * Universidad Carlos III de Madrid - Leganes (Madrid) - Spain |
8 | * Universidad Politecnica de Alcala de Henares - Alcala de H. (Madrid) - Spain | 8 | * Universidad Politecnica de Alcala de Henares - Alcala de H. (Madrid) - Spain |
9 | * email: fanton@it.uc3m.es | 9 | * email: fanton@it.uc3m.es |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/ipv6.h> | 18 | #include <linux/ipv6.h> |
19 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | #include <linux/netfilter.h> | 21 | #include <linux/netfilter.h> |
22 | #include <linux/netlink.h> | 22 | #include <linux/netlink.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/sysctl.h> | 24 | #include <linux/sysctl.h> |
25 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <net/net_namespace.h> | 29 | #include <net/net_namespace.h> |
30 | #include <net/sock.h> | 30 | #include <net/sock.h> |
31 | #include <net/ipv6.h> | 31 | #include <net/ipv6.h> |
32 | #include <net/ip6_route.h> | 32 | #include <net/ip6_route.h> |
33 | #include <net/netfilter/nf_queue.h> | 33 | #include <net/netfilter/nf_queue.h> |
34 | #include <linux/netfilter_ipv4/ip_queue.h> | 34 | #include <linux/netfilter_ipv4/ip_queue.h> |
35 | #include <linux/netfilter_ipv4/ip_tables.h> | 35 | #include <linux/netfilter_ipv4/ip_tables.h> |
36 | #include <linux/netfilter_ipv6/ip6_tables.h> | 36 | #include <linux/netfilter_ipv6/ip6_tables.h> |
37 | 37 | ||
38 | #define IPQ_QMAX_DEFAULT 1024 | 38 | #define IPQ_QMAX_DEFAULT 1024 |
39 | #define IPQ_PROC_FS_NAME "ip6_queue" | 39 | #define IPQ_PROC_FS_NAME "ip6_queue" |
40 | #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" | 40 | #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" |
41 | 41 | ||
42 | typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); | 42 | typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); |
43 | 43 | ||
44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; | 44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; |
45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; | 45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; |
46 | static DEFINE_SPINLOCK(queue_lock); | 46 | static DEFINE_SPINLOCK(queue_lock); |
47 | static int peer_pid __read_mostly; | 47 | static int peer_pid __read_mostly; |
48 | static unsigned int copy_range __read_mostly; | 48 | static unsigned int copy_range __read_mostly; |
49 | static unsigned int queue_total; | 49 | static unsigned int queue_total; |
50 | static unsigned int queue_dropped = 0; | 50 | static unsigned int queue_dropped = 0; |
51 | static unsigned int queue_user_dropped = 0; | 51 | static unsigned int queue_user_dropped = 0; |
52 | static struct sock *ipqnl __read_mostly; | 52 | static struct sock *ipqnl __read_mostly; |
53 | static LIST_HEAD(queue_list); | 53 | static LIST_HEAD(queue_list); |
54 | static DEFINE_MUTEX(ipqnl_mutex); | 54 | static DEFINE_MUTEX(ipqnl_mutex); |
55 | 55 | ||
56 | static inline void | 56 | static inline void |
57 | __ipq_enqueue_entry(struct nf_queue_entry *entry) | 57 | __ipq_enqueue_entry(struct nf_queue_entry *entry) |
58 | { | 58 | { |
59 | list_add_tail(&entry->list, &queue_list); | 59 | list_add_tail(&entry->list, &queue_list); |
60 | queue_total++; | 60 | queue_total++; |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline int | 63 | static inline int |
64 | __ipq_set_mode(unsigned char mode, unsigned int range) | 64 | __ipq_set_mode(unsigned char mode, unsigned int range) |
65 | { | 65 | { |
66 | int status = 0; | 66 | int status = 0; |
67 | 67 | ||
68 | switch(mode) { | 68 | switch(mode) { |
69 | case IPQ_COPY_NONE: | 69 | case IPQ_COPY_NONE: |
70 | case IPQ_COPY_META: | 70 | case IPQ_COPY_META: |
71 | copy_mode = mode; | 71 | copy_mode = mode; |
72 | copy_range = 0; | 72 | copy_range = 0; |
73 | break; | 73 | break; |
74 | 74 | ||
75 | case IPQ_COPY_PACKET: | 75 | case IPQ_COPY_PACKET: |
76 | if (range > 0xFFFF) | 76 | if (range > 0xFFFF) |
77 | range = 0xFFFF; | 77 | range = 0xFFFF; |
78 | copy_range = range; | 78 | copy_range = range; |
79 | copy_mode = mode; | 79 | copy_mode = mode; |
80 | break; | 80 | break; |
81 | 81 | ||
82 | default: | 82 | default: |
83 | status = -EINVAL; | 83 | status = -EINVAL; |
84 | 84 | ||
85 | } | 85 | } |
86 | return status; | 86 | return status; |
87 | } | 87 | } |
88 | 88 | ||
89 | static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data); | 89 | static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data); |
90 | 90 | ||
91 | static inline void | 91 | static inline void |
92 | __ipq_reset(void) | 92 | __ipq_reset(void) |
93 | { | 93 | { |
94 | peer_pid = 0; | 94 | peer_pid = 0; |
95 | net_disable_timestamp(); | 95 | net_disable_timestamp(); |
96 | __ipq_set_mode(IPQ_COPY_NONE, 0); | 96 | __ipq_set_mode(IPQ_COPY_NONE, 0); |
97 | __ipq_flush(NULL, 0); | 97 | __ipq_flush(NULL, 0); |
98 | } | 98 | } |
99 | 99 | ||
100 | static struct nf_queue_entry * | 100 | static struct nf_queue_entry * |
101 | ipq_find_dequeue_entry(unsigned long id) | 101 | ipq_find_dequeue_entry(unsigned long id) |
102 | { | 102 | { |
103 | struct nf_queue_entry *entry = NULL, *i; | 103 | struct nf_queue_entry *entry = NULL, *i; |
104 | 104 | ||
105 | spin_lock_bh(&queue_lock); | 105 | spin_lock_bh(&queue_lock); |
106 | 106 | ||
107 | list_for_each_entry(i, &queue_list, list) { | 107 | list_for_each_entry(i, &queue_list, list) { |
108 | if ((unsigned long)i == id) { | 108 | if ((unsigned long)i == id) { |
109 | entry = i; | 109 | entry = i; |
110 | break; | 110 | break; |
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | if (entry) { | 114 | if (entry) { |
115 | list_del(&entry->list); | 115 | list_del(&entry->list); |
116 | queue_total--; | 116 | queue_total--; |
117 | } | 117 | } |
118 | 118 | ||
119 | spin_unlock_bh(&queue_lock); | 119 | spin_unlock_bh(&queue_lock); |
120 | return entry; | 120 | return entry; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void | 123 | static void |
124 | __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 124 | __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
125 | { | 125 | { |
126 | struct nf_queue_entry *entry, *next; | 126 | struct nf_queue_entry *entry, *next; |
127 | 127 | ||
128 | list_for_each_entry_safe(entry, next, &queue_list, list) { | 128 | list_for_each_entry_safe(entry, next, &queue_list, list) { |
129 | if (!cmpfn || cmpfn(entry, data)) { | 129 | if (!cmpfn || cmpfn(entry, data)) { |
130 | list_del(&entry->list); | 130 | list_del(&entry->list); |
131 | queue_total--; | 131 | queue_total--; |
132 | nf_reinject(entry, NF_DROP); | 132 | nf_reinject(entry, NF_DROP); |
133 | } | 133 | } |
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | static void | 137 | static void |
138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
139 | { | 139 | { |
140 | spin_lock_bh(&queue_lock); | 140 | spin_lock_bh(&queue_lock); |
141 | __ipq_flush(cmpfn, data); | 141 | __ipq_flush(cmpfn, data); |
142 | spin_unlock_bh(&queue_lock); | 142 | spin_unlock_bh(&queue_lock); |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct sk_buff * | 145 | static struct sk_buff * |
146 | ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | 146 | ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) |
147 | { | 147 | { |
148 | sk_buff_data_t old_tail; | 148 | sk_buff_data_t old_tail; |
149 | size_t size = 0; | 149 | size_t size = 0; |
150 | size_t data_len = 0; | 150 | size_t data_len = 0; |
151 | struct sk_buff *skb; | 151 | struct sk_buff *skb; |
152 | struct ipq_packet_msg *pmsg; | 152 | struct ipq_packet_msg *pmsg; |
153 | struct nlmsghdr *nlh; | 153 | struct nlmsghdr *nlh; |
154 | struct timeval tv; | 154 | struct timeval tv; |
155 | 155 | ||
156 | switch (ACCESS_ONCE(copy_mode)) { | 156 | switch (ACCESS_ONCE(copy_mode)) { |
157 | case IPQ_COPY_META: | 157 | case IPQ_COPY_META: |
158 | case IPQ_COPY_NONE: | 158 | case IPQ_COPY_NONE: |
159 | size = NLMSG_SPACE(sizeof(*pmsg)); | 159 | size = NLMSG_SPACE(sizeof(*pmsg)); |
160 | break; | 160 | break; |
161 | 161 | ||
162 | case IPQ_COPY_PACKET: | 162 | case IPQ_COPY_PACKET: |
163 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && | 163 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
164 | (*errp = skb_checksum_help(entry->skb))) | 164 | (*errp = skb_checksum_help(entry->skb))) |
165 | return NULL; | 165 | return NULL; |
166 | 166 | ||
167 | data_len = ACCESS_ONCE(copy_range); | 167 | data_len = ACCESS_ONCE(copy_range); |
168 | if (data_len == 0 || data_len > entry->skb->len) | 168 | if (data_len == 0 || data_len > entry->skb->len) |
169 | data_len = entry->skb->len; | 169 | data_len = entry->skb->len; |
170 | 170 | ||
171 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); | 171 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); |
172 | break; | 172 | break; |
173 | 173 | ||
174 | default: | 174 | default: |
175 | *errp = -EINVAL; | 175 | *errp = -EINVAL; |
176 | return NULL; | 176 | return NULL; |
177 | } | 177 | } |
178 | 178 | ||
179 | skb = alloc_skb(size, GFP_ATOMIC); | 179 | skb = alloc_skb(size, GFP_ATOMIC); |
180 | if (!skb) | 180 | if (!skb) |
181 | goto nlmsg_failure; | 181 | goto nlmsg_failure; |
182 | 182 | ||
183 | old_tail = skb->tail; | 183 | old_tail = skb->tail; |
184 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); | 184 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); |
185 | pmsg = NLMSG_DATA(nlh); | 185 | pmsg = NLMSG_DATA(nlh); |
186 | memset(pmsg, 0, sizeof(*pmsg)); | 186 | memset(pmsg, 0, sizeof(*pmsg)); |
187 | 187 | ||
188 | pmsg->packet_id = (unsigned long )entry; | 188 | pmsg->packet_id = (unsigned long )entry; |
189 | pmsg->data_len = data_len; | 189 | pmsg->data_len = data_len; |
190 | tv = ktime_to_timeval(entry->skb->tstamp); | 190 | tv = ktime_to_timeval(entry->skb->tstamp); |
191 | pmsg->timestamp_sec = tv.tv_sec; | 191 | pmsg->timestamp_sec = tv.tv_sec; |
192 | pmsg->timestamp_usec = tv.tv_usec; | 192 | pmsg->timestamp_usec = tv.tv_usec; |
193 | pmsg->mark = entry->skb->mark; | 193 | pmsg->mark = entry->skb->mark; |
194 | pmsg->hook = entry->hook; | 194 | pmsg->hook = entry->hook; |
195 | pmsg->hw_protocol = entry->skb->protocol; | 195 | pmsg->hw_protocol = entry->skb->protocol; |
196 | 196 | ||
197 | if (entry->indev) | 197 | if (entry->indev) |
198 | strcpy(pmsg->indev_name, entry->indev->name); | 198 | strcpy(pmsg->indev_name, entry->indev->name); |
199 | else | 199 | else |
200 | pmsg->indev_name[0] = '\0'; | 200 | pmsg->indev_name[0] = '\0'; |
201 | 201 | ||
202 | if (entry->outdev) | 202 | if (entry->outdev) |
203 | strcpy(pmsg->outdev_name, entry->outdev->name); | 203 | strcpy(pmsg->outdev_name, entry->outdev->name); |
204 | else | 204 | else |
205 | pmsg->outdev_name[0] = '\0'; | 205 | pmsg->outdev_name[0] = '\0'; |
206 | 206 | ||
207 | if (entry->indev && entry->skb->dev && | 207 | if (entry->indev && entry->skb->dev && |
208 | entry->skb->mac_header != entry->skb->network_header) { | 208 | entry->skb->mac_header != entry->skb->network_header) { |
209 | pmsg->hw_type = entry->skb->dev->type; | 209 | pmsg->hw_type = entry->skb->dev->type; |
210 | pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); | 210 | pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); |
211 | } | 211 | } |
212 | 212 | ||
213 | if (data_len) | 213 | if (data_len) |
214 | if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len)) | 214 | if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len)) |
215 | BUG(); | 215 | BUG(); |
216 | 216 | ||
217 | nlh->nlmsg_len = skb->tail - old_tail; | 217 | nlh->nlmsg_len = skb->tail - old_tail; |
218 | return skb; | 218 | return skb; |
219 | 219 | ||
220 | nlmsg_failure: | 220 | nlmsg_failure: |
221 | kfree_skb(skb); | 221 | kfree_skb(skb); |
222 | *errp = -EINVAL; | 222 | *errp = -EINVAL; |
223 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); | 223 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); |
224 | return NULL; | 224 | return NULL; |
225 | } | 225 | } |
226 | 226 | ||
227 | static int | 227 | static int |
228 | ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | 228 | ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) |
229 | { | 229 | { |
230 | int status = -EINVAL; | 230 | int status = -EINVAL; |
231 | struct sk_buff *nskb; | 231 | struct sk_buff *nskb; |
232 | 232 | ||
233 | if (copy_mode == IPQ_COPY_NONE) | 233 | if (copy_mode == IPQ_COPY_NONE) |
234 | return -EAGAIN; | 234 | return -EAGAIN; |
235 | 235 | ||
236 | nskb = ipq_build_packet_message(entry, &status); | 236 | nskb = ipq_build_packet_message(entry, &status); |
237 | if (nskb == NULL) | 237 | if (nskb == NULL) |
238 | return status; | 238 | return status; |
239 | 239 | ||
240 | spin_lock_bh(&queue_lock); | 240 | spin_lock_bh(&queue_lock); |
241 | 241 | ||
242 | if (!peer_pid) | 242 | if (!peer_pid) |
243 | goto err_out_free_nskb; | 243 | goto err_out_free_nskb; |
244 | 244 | ||
245 | if (queue_total >= queue_maxlen) { | 245 | if (queue_total >= queue_maxlen) { |
246 | queue_dropped++; | 246 | queue_dropped++; |
247 | status = -ENOSPC; | 247 | status = -ENOSPC; |
248 | if (net_ratelimit()) | 248 | if (net_ratelimit()) |
249 | printk (KERN_WARNING "ip6_queue: fill at %d entries, " | 249 | printk (KERN_WARNING "ip6_queue: fill at %d entries, " |
250 | "dropping packet(s). Dropped: %d\n", queue_total, | 250 | "dropping packet(s). Dropped: %d\n", queue_total, |
251 | queue_dropped); | 251 | queue_dropped); |
252 | goto err_out_free_nskb; | 252 | goto err_out_free_nskb; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* netlink_unicast will either free the nskb or attach it to a socket */ | 255 | /* netlink_unicast will either free the nskb or attach it to a socket */ |
256 | status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); | 256 | status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); |
257 | if (status < 0) { | 257 | if (status < 0) { |
258 | queue_user_dropped++; | 258 | queue_user_dropped++; |
259 | goto err_out_unlock; | 259 | goto err_out_unlock; |
260 | } | 260 | } |
261 | 261 | ||
262 | __ipq_enqueue_entry(entry); | 262 | __ipq_enqueue_entry(entry); |
263 | 263 | ||
264 | spin_unlock_bh(&queue_lock); | 264 | spin_unlock_bh(&queue_lock); |
265 | return status; | 265 | return status; |
266 | 266 | ||
267 | err_out_free_nskb: | 267 | err_out_free_nskb: |
268 | kfree_skb(nskb); | 268 | kfree_skb(nskb); |
269 | 269 | ||
270 | err_out_unlock: | 270 | err_out_unlock: |
271 | spin_unlock_bh(&queue_lock); | 271 | spin_unlock_bh(&queue_lock); |
272 | return status; | 272 | return status; |
273 | } | 273 | } |
274 | 274 | ||
275 | static int | 275 | static int |
276 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e) | 276 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e) |
277 | { | 277 | { |
278 | int diff; | 278 | int diff; |
279 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; | 279 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; |
280 | struct sk_buff *nskb; | 280 | struct sk_buff *nskb; |
281 | 281 | ||
282 | if (v->data_len < sizeof(*user_iph)) | 282 | if (v->data_len < sizeof(*user_iph)) |
283 | return 0; | 283 | return 0; |
284 | diff = v->data_len - e->skb->len; | 284 | diff = v->data_len - e->skb->len; |
285 | if (diff < 0) { | 285 | if (diff < 0) { |
286 | if (pskb_trim(e->skb, v->data_len)) | 286 | if (pskb_trim(e->skb, v->data_len)) |
287 | return -ENOMEM; | 287 | return -ENOMEM; |
288 | } else if (diff > 0) { | 288 | } else if (diff > 0) { |
289 | if (v->data_len > 0xFFFF) | 289 | if (v->data_len > 0xFFFF) |
290 | return -EINVAL; | 290 | return -EINVAL; |
291 | if (diff > skb_tailroom(e->skb)) { | 291 | if (diff > skb_tailroom(e->skb)) { |
292 | nskb = skb_copy_expand(e->skb, skb_headroom(e->skb), | 292 | nskb = skb_copy_expand(e->skb, skb_headroom(e->skb), |
293 | diff, GFP_ATOMIC); | 293 | diff, GFP_ATOMIC); |
294 | if (!nskb) { | 294 | if (!nskb) { |
295 | printk(KERN_WARNING "ip6_queue: OOM " | 295 | printk(KERN_WARNING "ip6_queue: OOM " |
296 | "in mangle, dropping packet\n"); | 296 | "in mangle, dropping packet\n"); |
297 | return -ENOMEM; | 297 | return -ENOMEM; |
298 | } | 298 | } |
299 | kfree_skb(e->skb); | 299 | kfree_skb(e->skb); |
300 | e->skb = nskb; | 300 | e->skb = nskb; |
301 | } | 301 | } |
302 | skb_put(e->skb, diff); | 302 | skb_put(e->skb, diff); |
303 | } | 303 | } |
304 | if (!skb_make_writable(e->skb, v->data_len)) | 304 | if (!skb_make_writable(e->skb, v->data_len)) |
305 | return -ENOMEM; | 305 | return -ENOMEM; |
306 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 306 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
307 | e->skb->ip_summed = CHECKSUM_NONE; | 307 | e->skb->ip_summed = CHECKSUM_NONE; |
308 | 308 | ||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int | 312 | static int |
313 | ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) | 313 | ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) |
314 | { | 314 | { |
315 | struct nf_queue_entry *entry; | 315 | struct nf_queue_entry *entry; |
316 | 316 | ||
317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) | 317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) |
318 | return -EINVAL; | 318 | return -EINVAL; |
319 | 319 | ||
320 | entry = ipq_find_dequeue_entry(vmsg->id); | 320 | entry = ipq_find_dequeue_entry(vmsg->id); |
321 | if (entry == NULL) | 321 | if (entry == NULL) |
322 | return -ENOENT; | 322 | return -ENOENT; |
323 | else { | 323 | else { |
324 | int verdict = vmsg->value; | 324 | int verdict = vmsg->value; |
325 | 325 | ||
326 | if (vmsg->data_len && vmsg->data_len == len) | 326 | if (vmsg->data_len && vmsg->data_len == len) |
327 | if (ipq_mangle_ipv6(vmsg, entry) < 0) | 327 | if (ipq_mangle_ipv6(vmsg, entry) < 0) |
328 | verdict = NF_DROP; | 328 | verdict = NF_DROP; |
329 | 329 | ||
330 | nf_reinject(entry, verdict); | 330 | nf_reinject(entry, verdict); |
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | } | 333 | } |
334 | 334 | ||
335 | static int | 335 | static int |
336 | ipq_set_mode(unsigned char mode, unsigned int range) | 336 | ipq_set_mode(unsigned char mode, unsigned int range) |
337 | { | 337 | { |
338 | int status; | 338 | int status; |
339 | 339 | ||
340 | spin_lock_bh(&queue_lock); | 340 | spin_lock_bh(&queue_lock); |
341 | status = __ipq_set_mode(mode, range); | 341 | status = __ipq_set_mode(mode, range); |
342 | spin_unlock_bh(&queue_lock); | 342 | spin_unlock_bh(&queue_lock); |
343 | return status; | 343 | return status; |
344 | } | 344 | } |
345 | 345 | ||
346 | static int | 346 | static int |
347 | ipq_receive_peer(struct ipq_peer_msg *pmsg, | 347 | ipq_receive_peer(struct ipq_peer_msg *pmsg, |
348 | unsigned char type, unsigned int len) | 348 | unsigned char type, unsigned int len) |
349 | { | 349 | { |
350 | int status = 0; | 350 | int status = 0; |
351 | 351 | ||
352 | if (len < sizeof(*pmsg)) | 352 | if (len < sizeof(*pmsg)) |
353 | return -EINVAL; | 353 | return -EINVAL; |
354 | 354 | ||
355 | switch (type) { | 355 | switch (type) { |
356 | case IPQM_MODE: | 356 | case IPQM_MODE: |
357 | status = ipq_set_mode(pmsg->msg.mode.value, | 357 | status = ipq_set_mode(pmsg->msg.mode.value, |
358 | pmsg->msg.mode.range); | 358 | pmsg->msg.mode.range); |
359 | break; | 359 | break; |
360 | 360 | ||
361 | case IPQM_VERDICT: | 361 | case IPQM_VERDICT: |
362 | status = ipq_set_verdict(&pmsg->msg.verdict, | 362 | status = ipq_set_verdict(&pmsg->msg.verdict, |
363 | len - sizeof(*pmsg)); | 363 | len - sizeof(*pmsg)); |
364 | break; | 364 | break; |
365 | default: | 365 | default: |
366 | status = -EINVAL; | 366 | status = -EINVAL; |
367 | } | 367 | } |
368 | return status; | 368 | return status; |
369 | } | 369 | } |
370 | 370 | ||
371 | static int | 371 | static int |
372 | dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) | 372 | dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) |
373 | { | 373 | { |
374 | if (entry->indev) | 374 | if (entry->indev) |
375 | if (entry->indev->ifindex == ifindex) | 375 | if (entry->indev->ifindex == ifindex) |
376 | return 1; | 376 | return 1; |
377 | 377 | ||
378 | if (entry->outdev) | 378 | if (entry->outdev) |
379 | if (entry->outdev->ifindex == ifindex) | 379 | if (entry->outdev->ifindex == ifindex) |
380 | return 1; | 380 | return 1; |
381 | #ifdef CONFIG_BRIDGE_NETFILTER | 381 | #ifdef CONFIG_BRIDGE_NETFILTER |
382 | if (entry->skb->nf_bridge) { | 382 | if (entry->skb->nf_bridge) { |
383 | if (entry->skb->nf_bridge->physindev && | 383 | if (entry->skb->nf_bridge->physindev && |
384 | entry->skb->nf_bridge->physindev->ifindex == ifindex) | 384 | entry->skb->nf_bridge->physindev->ifindex == ifindex) |
385 | return 1; | 385 | return 1; |
386 | if (entry->skb->nf_bridge->physoutdev && | 386 | if (entry->skb->nf_bridge->physoutdev && |
387 | entry->skb->nf_bridge->physoutdev->ifindex == ifindex) | 387 | entry->skb->nf_bridge->physoutdev->ifindex == ifindex) |
388 | return 1; | 388 | return 1; |
389 | } | 389 | } |
390 | #endif | 390 | #endif |
391 | return 0; | 391 | return 0; |
392 | } | 392 | } |
393 | 393 | ||
394 | static void | 394 | static void |
395 | ipq_dev_drop(int ifindex) | 395 | ipq_dev_drop(int ifindex) |
396 | { | 396 | { |
397 | ipq_flush(dev_cmp, ifindex); | 397 | ipq_flush(dev_cmp, ifindex); |
398 | } | 398 | } |
399 | 399 | ||
400 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) | 400 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
401 | 401 | ||
402 | static inline void | 402 | static inline void |
403 | __ipq_rcv_skb(struct sk_buff *skb) | 403 | __ipq_rcv_skb(struct sk_buff *skb) |
404 | { | 404 | { |
405 | int status, type, pid, flags; | 405 | int status, type, pid, flags; |
406 | unsigned int nlmsglen, skblen; | 406 | unsigned int nlmsglen, skblen; |
407 | struct nlmsghdr *nlh; | 407 | struct nlmsghdr *nlh; |
408 | 408 | ||
409 | skblen = skb->len; | 409 | skblen = skb->len; |
410 | if (skblen < sizeof(*nlh)) | 410 | if (skblen < sizeof(*nlh)) |
411 | return; | 411 | return; |
412 | 412 | ||
413 | nlh = nlmsg_hdr(skb); | 413 | nlh = nlmsg_hdr(skb); |
414 | nlmsglen = nlh->nlmsg_len; | 414 | nlmsglen = nlh->nlmsg_len; |
415 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) | 415 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) |
416 | return; | 416 | return; |
417 | 417 | ||
418 | pid = nlh->nlmsg_pid; | 418 | pid = nlh->nlmsg_pid; |
419 | flags = nlh->nlmsg_flags; | 419 | flags = nlh->nlmsg_flags; |
420 | 420 | ||
421 | if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) | 421 | if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) |
422 | RCV_SKB_FAIL(-EINVAL); | 422 | RCV_SKB_FAIL(-EINVAL); |
423 | 423 | ||
424 | if (flags & MSG_TRUNC) | 424 | if (flags & MSG_TRUNC) |
425 | RCV_SKB_FAIL(-ECOMM); | 425 | RCV_SKB_FAIL(-ECOMM); |
426 | 426 | ||
427 | type = nlh->nlmsg_type; | 427 | type = nlh->nlmsg_type; |
428 | if (type < NLMSG_NOOP || type >= IPQM_MAX) | 428 | if (type < NLMSG_NOOP || type >= IPQM_MAX) |
429 | RCV_SKB_FAIL(-EINVAL); | 429 | RCV_SKB_FAIL(-EINVAL); |
430 | 430 | ||
431 | if (type <= IPQM_BASE) | 431 | if (type <= IPQM_BASE) |
432 | return; | 432 | return; |
433 | 433 | ||
434 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 434 | if (!capable(CAP_NET_ADMIN)) |
435 | RCV_SKB_FAIL(-EPERM); | 435 | RCV_SKB_FAIL(-EPERM); |
436 | 436 | ||
437 | spin_lock_bh(&queue_lock); | 437 | spin_lock_bh(&queue_lock); |
438 | 438 | ||
439 | if (peer_pid) { | 439 | if (peer_pid) { |
440 | if (peer_pid != pid) { | 440 | if (peer_pid != pid) { |
441 | spin_unlock_bh(&queue_lock); | 441 | spin_unlock_bh(&queue_lock); |
442 | RCV_SKB_FAIL(-EBUSY); | 442 | RCV_SKB_FAIL(-EBUSY); |
443 | } | 443 | } |
444 | } else { | 444 | } else { |
445 | net_enable_timestamp(); | 445 | net_enable_timestamp(); |
446 | peer_pid = pid; | 446 | peer_pid = pid; |
447 | } | 447 | } |
448 | 448 | ||
449 | spin_unlock_bh(&queue_lock); | 449 | spin_unlock_bh(&queue_lock); |
450 | 450 | ||
451 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 451 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
452 | nlmsglen - NLMSG_LENGTH(0)); | 452 | nlmsglen - NLMSG_LENGTH(0)); |
453 | if (status < 0) | 453 | if (status < 0) |
454 | RCV_SKB_FAIL(status); | 454 | RCV_SKB_FAIL(status); |
455 | 455 | ||
456 | if (flags & NLM_F_ACK) | 456 | if (flags & NLM_F_ACK) |
457 | netlink_ack(skb, nlh, 0); | 457 | netlink_ack(skb, nlh, 0); |
458 | } | 458 | } |
459 | 459 | ||
460 | static void | 460 | static void |
461 | ipq_rcv_skb(struct sk_buff *skb) | 461 | ipq_rcv_skb(struct sk_buff *skb) |
462 | { | 462 | { |
463 | mutex_lock(&ipqnl_mutex); | 463 | mutex_lock(&ipqnl_mutex); |
464 | __ipq_rcv_skb(skb); | 464 | __ipq_rcv_skb(skb); |
465 | mutex_unlock(&ipqnl_mutex); | 465 | mutex_unlock(&ipqnl_mutex); |
466 | } | 466 | } |
467 | 467 | ||
468 | static int | 468 | static int |
469 | ipq_rcv_dev_event(struct notifier_block *this, | 469 | ipq_rcv_dev_event(struct notifier_block *this, |
470 | unsigned long event, void *ptr) | 470 | unsigned long event, void *ptr) |
471 | { | 471 | { |
472 | struct net_device *dev = ptr; | 472 | struct net_device *dev = ptr; |
473 | 473 | ||
474 | if (!net_eq(dev_net(dev), &init_net)) | 474 | if (!net_eq(dev_net(dev), &init_net)) |
475 | return NOTIFY_DONE; | 475 | return NOTIFY_DONE; |
476 | 476 | ||
477 | /* Drop any packets associated with the downed device */ | 477 | /* Drop any packets associated with the downed device */ |
478 | if (event == NETDEV_DOWN) | 478 | if (event == NETDEV_DOWN) |
479 | ipq_dev_drop(dev->ifindex); | 479 | ipq_dev_drop(dev->ifindex); |
480 | return NOTIFY_DONE; | 480 | return NOTIFY_DONE; |
481 | } | 481 | } |
482 | 482 | ||
483 | static struct notifier_block ipq_dev_notifier = { | 483 | static struct notifier_block ipq_dev_notifier = { |
484 | .notifier_call = ipq_rcv_dev_event, | 484 | .notifier_call = ipq_rcv_dev_event, |
485 | }; | 485 | }; |
486 | 486 | ||
487 | static int | 487 | static int |
488 | ipq_rcv_nl_event(struct notifier_block *this, | 488 | ipq_rcv_nl_event(struct notifier_block *this, |
489 | unsigned long event, void *ptr) | 489 | unsigned long event, void *ptr) |
490 | { | 490 | { |
491 | struct netlink_notify *n = ptr; | 491 | struct netlink_notify *n = ptr; |
492 | 492 | ||
493 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { | 493 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { |
494 | spin_lock_bh(&queue_lock); | 494 | spin_lock_bh(&queue_lock); |
495 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 495 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
496 | __ipq_reset(); | 496 | __ipq_reset(); |
497 | spin_unlock_bh(&queue_lock); | 497 | spin_unlock_bh(&queue_lock); |
498 | } | 498 | } |
499 | return NOTIFY_DONE; | 499 | return NOTIFY_DONE; |
500 | } | 500 | } |
501 | 501 | ||
502 | static struct notifier_block ipq_nl_notifier = { | 502 | static struct notifier_block ipq_nl_notifier = { |
503 | .notifier_call = ipq_rcv_nl_event, | 503 | .notifier_call = ipq_rcv_nl_event, |
504 | }; | 504 | }; |
505 | 505 | ||
506 | #ifdef CONFIG_SYSCTL | 506 | #ifdef CONFIG_SYSCTL |
507 | static struct ctl_table_header *ipq_sysctl_header; | 507 | static struct ctl_table_header *ipq_sysctl_header; |
508 | 508 | ||
509 | static ctl_table ipq_table[] = { | 509 | static ctl_table ipq_table[] = { |
510 | { | 510 | { |
511 | .procname = NET_IPQ_QMAX_NAME, | 511 | .procname = NET_IPQ_QMAX_NAME, |
512 | .data = &queue_maxlen, | 512 | .data = &queue_maxlen, |
513 | .maxlen = sizeof(queue_maxlen), | 513 | .maxlen = sizeof(queue_maxlen), |
514 | .mode = 0644, | 514 | .mode = 0644, |
515 | .proc_handler = proc_dointvec | 515 | .proc_handler = proc_dointvec |
516 | }, | 516 | }, |
517 | { } | 517 | { } |
518 | }; | 518 | }; |
519 | #endif | 519 | #endif |
520 | 520 | ||
521 | #ifdef CONFIG_PROC_FS | 521 | #ifdef CONFIG_PROC_FS |
522 | static int ip6_queue_show(struct seq_file *m, void *v) | 522 | static int ip6_queue_show(struct seq_file *m, void *v) |
523 | { | 523 | { |
524 | spin_lock_bh(&queue_lock); | 524 | spin_lock_bh(&queue_lock); |
525 | 525 | ||
526 | seq_printf(m, | 526 | seq_printf(m, |
527 | "Peer PID : %d\n" | 527 | "Peer PID : %d\n" |
528 | "Copy mode : %hu\n" | 528 | "Copy mode : %hu\n" |
529 | "Copy range : %u\n" | 529 | "Copy range : %u\n" |
530 | "Queue length : %u\n" | 530 | "Queue length : %u\n" |
531 | "Queue max. length : %u\n" | 531 | "Queue max. length : %u\n" |
532 | "Queue dropped : %u\n" | 532 | "Queue dropped : %u\n" |
533 | "Netfilter dropped : %u\n", | 533 | "Netfilter dropped : %u\n", |
534 | peer_pid, | 534 | peer_pid, |
535 | copy_mode, | 535 | copy_mode, |
536 | copy_range, | 536 | copy_range, |
537 | queue_total, | 537 | queue_total, |
538 | queue_maxlen, | 538 | queue_maxlen, |
539 | queue_dropped, | 539 | queue_dropped, |
540 | queue_user_dropped); | 540 | queue_user_dropped); |
541 | 541 | ||
542 | spin_unlock_bh(&queue_lock); | 542 | spin_unlock_bh(&queue_lock); |
543 | return 0; | 543 | return 0; |
544 | } | 544 | } |
545 | 545 | ||
546 | static int ip6_queue_open(struct inode *inode, struct file *file) | 546 | static int ip6_queue_open(struct inode *inode, struct file *file) |
547 | { | 547 | { |
548 | return single_open(file, ip6_queue_show, NULL); | 548 | return single_open(file, ip6_queue_show, NULL); |
549 | } | 549 | } |
550 | 550 | ||
551 | static const struct file_operations ip6_queue_proc_fops = { | 551 | static const struct file_operations ip6_queue_proc_fops = { |
552 | .open = ip6_queue_open, | 552 | .open = ip6_queue_open, |
553 | .read = seq_read, | 553 | .read = seq_read, |
554 | .llseek = seq_lseek, | 554 | .llseek = seq_lseek, |
555 | .release = single_release, | 555 | .release = single_release, |
556 | .owner = THIS_MODULE, | 556 | .owner = THIS_MODULE, |
557 | }; | 557 | }; |
558 | #endif | 558 | #endif |
559 | 559 | ||
560 | static const struct nf_queue_handler nfqh = { | 560 | static const struct nf_queue_handler nfqh = { |
561 | .name = "ip6_queue", | 561 | .name = "ip6_queue", |
562 | .outfn = &ipq_enqueue_packet, | 562 | .outfn = &ipq_enqueue_packet, |
563 | }; | 563 | }; |
564 | 564 | ||
565 | static int __init ip6_queue_init(void) | 565 | static int __init ip6_queue_init(void) |
566 | { | 566 | { |
567 | int status = -ENOMEM; | 567 | int status = -ENOMEM; |
568 | struct proc_dir_entry *proc __maybe_unused; | 568 | struct proc_dir_entry *proc __maybe_unused; |
569 | 569 | ||
570 | netlink_register_notifier(&ipq_nl_notifier); | 570 | netlink_register_notifier(&ipq_nl_notifier); |
571 | ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, | 571 | ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, |
572 | ipq_rcv_skb, NULL, THIS_MODULE); | 572 | ipq_rcv_skb, NULL, THIS_MODULE); |
573 | if (ipqnl == NULL) { | 573 | if (ipqnl == NULL) { |
574 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); | 574 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); |
575 | goto cleanup_netlink_notifier; | 575 | goto cleanup_netlink_notifier; |
576 | } | 576 | } |
577 | 577 | ||
578 | #ifdef CONFIG_PROC_FS | 578 | #ifdef CONFIG_PROC_FS |
579 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, | 579 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, |
580 | &ip6_queue_proc_fops); | 580 | &ip6_queue_proc_fops); |
581 | if (!proc) { | 581 | if (!proc) { |
582 | printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); | 582 | printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); |
583 | goto cleanup_ipqnl; | 583 | goto cleanup_ipqnl; |
584 | } | 584 | } |
585 | #endif | 585 | #endif |
586 | register_netdevice_notifier(&ipq_dev_notifier); | 586 | register_netdevice_notifier(&ipq_dev_notifier); |
587 | #ifdef CONFIG_SYSCTL | 587 | #ifdef CONFIG_SYSCTL |
588 | ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); | 588 | ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); |
589 | #endif | 589 | #endif |
590 | status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh); | 590 | status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh); |
591 | if (status < 0) { | 591 | if (status < 0) { |
592 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); | 592 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); |
593 | goto cleanup_sysctl; | 593 | goto cleanup_sysctl; |
594 | } | 594 | } |
595 | return status; | 595 | return status; |
596 | 596 | ||
597 | cleanup_sysctl: | 597 | cleanup_sysctl: |
598 | #ifdef CONFIG_SYSCTL | 598 | #ifdef CONFIG_SYSCTL |
599 | unregister_sysctl_table(ipq_sysctl_header); | 599 | unregister_sysctl_table(ipq_sysctl_header); |
600 | #endif | 600 | #endif |
601 | unregister_netdevice_notifier(&ipq_dev_notifier); | 601 | unregister_netdevice_notifier(&ipq_dev_notifier); |
602 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); | 602 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); |
603 | 603 | ||
604 | cleanup_ipqnl: __maybe_unused | 604 | cleanup_ipqnl: __maybe_unused |
605 | netlink_kernel_release(ipqnl); | 605 | netlink_kernel_release(ipqnl); |
606 | mutex_lock(&ipqnl_mutex); | 606 | mutex_lock(&ipqnl_mutex); |
607 | mutex_unlock(&ipqnl_mutex); | 607 | mutex_unlock(&ipqnl_mutex); |
608 | 608 | ||
609 | cleanup_netlink_notifier: | 609 | cleanup_netlink_notifier: |
610 | netlink_unregister_notifier(&ipq_nl_notifier); | 610 | netlink_unregister_notifier(&ipq_nl_notifier); |
611 | return status; | 611 | return status; |
612 | } | 612 | } |
613 | 613 | ||
614 | static void __exit ip6_queue_fini(void) | 614 | static void __exit ip6_queue_fini(void) |
615 | { | 615 | { |
616 | nf_unregister_queue_handlers(&nfqh); | 616 | nf_unregister_queue_handlers(&nfqh); |
617 | 617 | ||
618 | ipq_flush(NULL, 0); | 618 | ipq_flush(NULL, 0); |
619 | 619 | ||
620 | #ifdef CONFIG_SYSCTL | 620 | #ifdef CONFIG_SYSCTL |
621 | unregister_sysctl_table(ipq_sysctl_header); | 621 | unregister_sysctl_table(ipq_sysctl_header); |
622 | #endif | 622 | #endif |
623 | unregister_netdevice_notifier(&ipq_dev_notifier); | 623 | unregister_netdevice_notifier(&ipq_dev_notifier); |
624 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); | 624 | proc_net_remove(&init_net, IPQ_PROC_FS_NAME); |
625 | 625 | ||
626 | netlink_kernel_release(ipqnl); | 626 | netlink_kernel_release(ipqnl); |
627 | mutex_lock(&ipqnl_mutex); | 627 | mutex_lock(&ipqnl_mutex); |
628 | mutex_unlock(&ipqnl_mutex); | 628 | mutex_unlock(&ipqnl_mutex); |
629 | 629 | ||
630 | netlink_unregister_notifier(&ipq_nl_notifier); | 630 | netlink_unregister_notifier(&ipq_nl_notifier); |
631 | } | 631 | } |
632 | 632 | ||
633 | MODULE_DESCRIPTION("IPv6 packet queue handler"); | 633 | MODULE_DESCRIPTION("IPv6 packet queue handler"); |
634 | MODULE_LICENSE("GPL"); | 634 | MODULE_LICENSE("GPL"); |
635 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW); | 635 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW); |
636 | 636 | ||
637 | module_init(ip6_queue_init); | 637 | module_init(ip6_queue_init); |
638 | module_exit(ip6_queue_fini); | 638 | module_exit(ip6_queue_fini); |
639 | 639 |
net/netfilter/nfnetlink.c
1 | /* Netfilter messages via netlink socket. Allows for user space | 1 | /* Netfilter messages via netlink socket. Allows for user space |
2 | * protocol helpers and general trouble making from userspace. | 2 | * protocol helpers and general trouble making from userspace. |
3 | * | 3 | * |
4 | * (C) 2001 by Jay Schulist <jschlst@samba.org>, | 4 | * (C) 2001 by Jay Schulist <jschlst@samba.org>, |
5 | * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> | 5 | * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> |
6 | * (C) 2005,2007 by Pablo Neira Ayuso <pablo@netfilter.org> | 6 | * (C) 2005,2007 by Pablo Neira Ayuso <pablo@netfilter.org> |
7 | * | 7 | * |
8 | * Initial netfilter messages via netlink development funded and | 8 | * Initial netfilter messages via netlink development funded and |
9 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) | 9 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) |
10 | * | 10 | * |
11 | * Further development of this code funded by Astaro AG (http://www.astaro.com) | 11 | * Further development of this code funded by Astaro AG (http://www.astaro.com) |
12 | * | 12 | * |
13 | * This software may be used and distributed according to the terms | 13 | * This software may be used and distributed according to the terms |
14 | * of the GNU General Public License, incorporated herein by reference. | 14 | * of the GNU General Public License, incorporated herein by reference. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/socket.h> | 19 | #include <linux/socket.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/sockios.h> | 22 | #include <linux/sockios.h> |
23 | #include <linux/net.h> | 23 | #include <linux/net.h> |
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/system.h> | 26 | #include <asm/system.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/netlink.h> | 28 | #include <net/netlink.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | 30 | ||
31 | #include <linux/netlink.h> | 31 | #include <linux/netlink.h> |
32 | #include <linux/netfilter/nfnetlink.h> | 32 | #include <linux/netfilter/nfnetlink.h> |
33 | 33 | ||
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 35 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
36 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); | 36 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); |
37 | 37 | ||
38 | static char __initdata nfversion[] = "0.30"; | 38 | static char __initdata nfversion[] = "0.30"; |
39 | 39 | ||
40 | static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT]; | 40 | static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT]; |
41 | static DEFINE_MUTEX(nfnl_mutex); | 41 | static DEFINE_MUTEX(nfnl_mutex); |
42 | 42 | ||
43 | void nfnl_lock(void) | 43 | void nfnl_lock(void) |
44 | { | 44 | { |
45 | mutex_lock(&nfnl_mutex); | 45 | mutex_lock(&nfnl_mutex); |
46 | } | 46 | } |
47 | EXPORT_SYMBOL_GPL(nfnl_lock); | 47 | EXPORT_SYMBOL_GPL(nfnl_lock); |
48 | 48 | ||
49 | void nfnl_unlock(void) | 49 | void nfnl_unlock(void) |
50 | { | 50 | { |
51 | mutex_unlock(&nfnl_mutex); | 51 | mutex_unlock(&nfnl_mutex); |
52 | } | 52 | } |
53 | EXPORT_SYMBOL_GPL(nfnl_unlock); | 53 | EXPORT_SYMBOL_GPL(nfnl_unlock); |
54 | 54 | ||
55 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) | 55 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) |
56 | { | 56 | { |
57 | nfnl_lock(); | 57 | nfnl_lock(); |
58 | if (subsys_table[n->subsys_id]) { | 58 | if (subsys_table[n->subsys_id]) { |
59 | nfnl_unlock(); | 59 | nfnl_unlock(); |
60 | return -EBUSY; | 60 | return -EBUSY; |
61 | } | 61 | } |
62 | rcu_assign_pointer(subsys_table[n->subsys_id], n); | 62 | rcu_assign_pointer(subsys_table[n->subsys_id], n); |
63 | nfnl_unlock(); | 63 | nfnl_unlock(); |
64 | 64 | ||
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | EXPORT_SYMBOL_GPL(nfnetlink_subsys_register); | 67 | EXPORT_SYMBOL_GPL(nfnetlink_subsys_register); |
68 | 68 | ||
69 | int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) | 69 | int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) |
70 | { | 70 | { |
71 | nfnl_lock(); | 71 | nfnl_lock(); |
72 | subsys_table[n->subsys_id] = NULL; | 72 | subsys_table[n->subsys_id] = NULL; |
73 | nfnl_unlock(); | 73 | nfnl_unlock(); |
74 | synchronize_rcu(); | 74 | synchronize_rcu(); |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); | 77 | EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); |
78 | 78 | ||
79 | static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type) | 79 | static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type) |
80 | { | 80 | { |
81 | u_int8_t subsys_id = NFNL_SUBSYS_ID(type); | 81 | u_int8_t subsys_id = NFNL_SUBSYS_ID(type); |
82 | 82 | ||
83 | if (subsys_id >= NFNL_SUBSYS_COUNT) | 83 | if (subsys_id >= NFNL_SUBSYS_COUNT) |
84 | return NULL; | 84 | return NULL; |
85 | 85 | ||
86 | return rcu_dereference(subsys_table[subsys_id]); | 86 | return rcu_dereference(subsys_table[subsys_id]); |
87 | } | 87 | } |
88 | 88 | ||
89 | static inline const struct nfnl_callback * | 89 | static inline const struct nfnl_callback * |
90 | nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss) | 90 | nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss) |
91 | { | 91 | { |
92 | u_int8_t cb_id = NFNL_MSG_TYPE(type); | 92 | u_int8_t cb_id = NFNL_MSG_TYPE(type); |
93 | 93 | ||
94 | if (cb_id >= ss->cb_count) | 94 | if (cb_id >= ss->cb_count) |
95 | return NULL; | 95 | return NULL; |
96 | 96 | ||
97 | return &ss->cb[cb_id]; | 97 | return &ss->cb[cb_id]; |
98 | } | 98 | } |
99 | 99 | ||
100 | int nfnetlink_has_listeners(struct net *net, unsigned int group) | 100 | int nfnetlink_has_listeners(struct net *net, unsigned int group) |
101 | { | 101 | { |
102 | return netlink_has_listeners(net->nfnl, group); | 102 | return netlink_has_listeners(net->nfnl, group); |
103 | } | 103 | } |
104 | EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); | 104 | EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); |
105 | 105 | ||
106 | int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, | 106 | int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, |
107 | unsigned group, int echo, gfp_t flags) | 107 | unsigned group, int echo, gfp_t flags) |
108 | { | 108 | { |
109 | return nlmsg_notify(net->nfnl, skb, pid, group, echo, flags); | 109 | return nlmsg_notify(net->nfnl, skb, pid, group, echo, flags); |
110 | } | 110 | } |
111 | EXPORT_SYMBOL_GPL(nfnetlink_send); | 111 | EXPORT_SYMBOL_GPL(nfnetlink_send); |
112 | 112 | ||
113 | int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) | 113 | int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) |
114 | { | 114 | { |
115 | return netlink_set_err(net->nfnl, pid, group, error); | 115 | return netlink_set_err(net->nfnl, pid, group, error); |
116 | } | 116 | } |
117 | EXPORT_SYMBOL_GPL(nfnetlink_set_err); | 117 | EXPORT_SYMBOL_GPL(nfnetlink_set_err); |
118 | 118 | ||
119 | int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags) | 119 | int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags) |
120 | { | 120 | { |
121 | return netlink_unicast(net->nfnl, skb, pid, flags); | 121 | return netlink_unicast(net->nfnl, skb, pid, flags); |
122 | } | 122 | } |
123 | EXPORT_SYMBOL_GPL(nfnetlink_unicast); | 123 | EXPORT_SYMBOL_GPL(nfnetlink_unicast); |
124 | 124 | ||
125 | /* Process one complete nfnetlink message. */ | 125 | /* Process one complete nfnetlink message. */ |
126 | static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 126 | static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
127 | { | 127 | { |
128 | struct net *net = sock_net(skb->sk); | 128 | struct net *net = sock_net(skb->sk); |
129 | const struct nfnl_callback *nc; | 129 | const struct nfnl_callback *nc; |
130 | const struct nfnetlink_subsystem *ss; | 130 | const struct nfnetlink_subsystem *ss; |
131 | int type, err; | 131 | int type, err; |
132 | 132 | ||
133 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 133 | if (!capable(CAP_NET_ADMIN)) |
134 | return -EPERM; | 134 | return -EPERM; |
135 | 135 | ||
136 | /* All the messages must at least contain nfgenmsg */ | 136 | /* All the messages must at least contain nfgenmsg */ |
137 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) | 137 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) |
138 | return 0; | 138 | return 0; |
139 | 139 | ||
140 | type = nlh->nlmsg_type; | 140 | type = nlh->nlmsg_type; |
141 | replay: | 141 | replay: |
142 | rcu_read_lock(); | 142 | rcu_read_lock(); |
143 | ss = nfnetlink_get_subsys(type); | 143 | ss = nfnetlink_get_subsys(type); |
144 | if (!ss) { | 144 | if (!ss) { |
145 | #ifdef CONFIG_MODULES | 145 | #ifdef CONFIG_MODULES |
146 | rcu_read_unlock(); | 146 | rcu_read_unlock(); |
147 | request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); | 147 | request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); |
148 | rcu_read_lock(); | 148 | rcu_read_lock(); |
149 | ss = nfnetlink_get_subsys(type); | 149 | ss = nfnetlink_get_subsys(type); |
150 | if (!ss) | 150 | if (!ss) |
151 | #endif | 151 | #endif |
152 | { | 152 | { |
153 | rcu_read_unlock(); | 153 | rcu_read_unlock(); |
154 | return -EINVAL; | 154 | return -EINVAL; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | nc = nfnetlink_find_client(type, ss); | 158 | nc = nfnetlink_find_client(type, ss); |
159 | if (!nc) { | 159 | if (!nc) { |
160 | rcu_read_unlock(); | 160 | rcu_read_unlock(); |
161 | return -EINVAL; | 161 | return -EINVAL; |
162 | } | 162 | } |
163 | 163 | ||
164 | { | 164 | { |
165 | int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); | 165 | int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); |
166 | u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); | 166 | u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); |
167 | struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; | 167 | struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; |
168 | struct nlattr *attr = (void *)nlh + min_len; | 168 | struct nlattr *attr = (void *)nlh + min_len; |
169 | int attrlen = nlh->nlmsg_len - min_len; | 169 | int attrlen = nlh->nlmsg_len - min_len; |
170 | 170 | ||
171 | err = nla_parse(cda, ss->cb[cb_id].attr_count, | 171 | err = nla_parse(cda, ss->cb[cb_id].attr_count, |
172 | attr, attrlen, ss->cb[cb_id].policy); | 172 | attr, attrlen, ss->cb[cb_id].policy); |
173 | if (err < 0) | 173 | if (err < 0) |
174 | return err; | 174 | return err; |
175 | 175 | ||
176 | if (nc->call_rcu) { | 176 | if (nc->call_rcu) { |
177 | err = nc->call_rcu(net->nfnl, skb, nlh, | 177 | err = nc->call_rcu(net->nfnl, skb, nlh, |
178 | (const struct nlattr **)cda); | 178 | (const struct nlattr **)cda); |
179 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
180 | } else { | 180 | } else { |
181 | rcu_read_unlock(); | 181 | rcu_read_unlock(); |
182 | nfnl_lock(); | 182 | nfnl_lock(); |
183 | if (rcu_dereference_protected( | 183 | if (rcu_dereference_protected( |
184 | subsys_table[NFNL_SUBSYS_ID(type)], | 184 | subsys_table[NFNL_SUBSYS_ID(type)], |
185 | lockdep_is_held(&nfnl_mutex)) != ss || | 185 | lockdep_is_held(&nfnl_mutex)) != ss || |
186 | nfnetlink_find_client(type, ss) != nc) | 186 | nfnetlink_find_client(type, ss) != nc) |
187 | err = -EAGAIN; | 187 | err = -EAGAIN; |
188 | else | 188 | else |
189 | err = nc->call(net->nfnl, skb, nlh, | 189 | err = nc->call(net->nfnl, skb, nlh, |
190 | (const struct nlattr **)cda); | 190 | (const struct nlattr **)cda); |
191 | nfnl_unlock(); | 191 | nfnl_unlock(); |
192 | } | 192 | } |
193 | if (err == -EAGAIN) | 193 | if (err == -EAGAIN) |
194 | goto replay; | 194 | goto replay; |
195 | return err; | 195 | return err; |
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | static void nfnetlink_rcv(struct sk_buff *skb) | 199 | static void nfnetlink_rcv(struct sk_buff *skb) |
200 | { | 200 | { |
201 | netlink_rcv_skb(skb, &nfnetlink_rcv_msg); | 201 | netlink_rcv_skb(skb, &nfnetlink_rcv_msg); |
202 | } | 202 | } |
203 | 203 | ||
204 | static int __net_init nfnetlink_net_init(struct net *net) | 204 | static int __net_init nfnetlink_net_init(struct net *net) |
205 | { | 205 | { |
206 | struct sock *nfnl; | 206 | struct sock *nfnl; |
207 | 207 | ||
208 | nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX, | 208 | nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX, |
209 | nfnetlink_rcv, NULL, THIS_MODULE); | 209 | nfnetlink_rcv, NULL, THIS_MODULE); |
210 | if (!nfnl) | 210 | if (!nfnl) |
211 | return -ENOMEM; | 211 | return -ENOMEM; |
212 | net->nfnl_stash = nfnl; | 212 | net->nfnl_stash = nfnl; |
213 | rcu_assign_pointer(net->nfnl, nfnl); | 213 | rcu_assign_pointer(net->nfnl, nfnl); |
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list) | 217 | static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list) |
218 | { | 218 | { |
219 | struct net *net; | 219 | struct net *net; |
220 | 220 | ||
221 | list_for_each_entry(net, net_exit_list, exit_list) | 221 | list_for_each_entry(net, net_exit_list, exit_list) |
222 | rcu_assign_pointer(net->nfnl, NULL); | 222 | rcu_assign_pointer(net->nfnl, NULL); |
223 | synchronize_net(); | 223 | synchronize_net(); |
224 | list_for_each_entry(net, net_exit_list, exit_list) | 224 | list_for_each_entry(net, net_exit_list, exit_list) |
225 | netlink_kernel_release(net->nfnl_stash); | 225 | netlink_kernel_release(net->nfnl_stash); |
226 | } | 226 | } |
227 | 227 | ||
228 | static struct pernet_operations nfnetlink_net_ops = { | 228 | static struct pernet_operations nfnetlink_net_ops = { |
229 | .init = nfnetlink_net_init, | 229 | .init = nfnetlink_net_init, |
230 | .exit_batch = nfnetlink_net_exit_batch, | 230 | .exit_batch = nfnetlink_net_exit_batch, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static int __init nfnetlink_init(void) | 233 | static int __init nfnetlink_init(void) |
234 | { | 234 | { |
235 | pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); | 235 | pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); |
236 | return register_pernet_subsys(&nfnetlink_net_ops); | 236 | return register_pernet_subsys(&nfnetlink_net_ops); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void __exit nfnetlink_exit(void) | 239 | static void __exit nfnetlink_exit(void) |
240 | { | 240 | { |
241 | pr_info("Removing netfilter NETLINK layer.\n"); | 241 | pr_info("Removing netfilter NETLINK layer.\n"); |
242 | unregister_pernet_subsys(&nfnetlink_net_ops); | 242 | unregister_pernet_subsys(&nfnetlink_net_ops); |
243 | } | 243 | } |
244 | module_init(nfnetlink_init); | 244 | module_init(nfnetlink_init); |
245 | module_exit(nfnetlink_exit); | 245 | module_exit(nfnetlink_exit); |
246 | 246 |
net/netlink/genetlink.c
1 | /* | 1 | /* |
2 | * NETLINK Generic Netlink Family | 2 | * NETLINK Generic Netlink Family |
3 | * | 3 | * |
4 | * Authors: Jamal Hadi Salim | 4 | * Authors: Jamal Hadi Salim |
5 | * Thomas Graf <tgraf@suug.ch> | 5 | * Thomas Graf <tgraf@suug.ch> |
6 | * Johannes Berg <johannes@sipsolutions.net> | 6 | * Johannes Berg <johannes@sipsolutions.net> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/socket.h> | 14 | #include <linux/socket.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/bitmap.h> | 18 | #include <linux/bitmap.h> |
19 | #include <net/sock.h> | 19 | #include <net/sock.h> |
20 | #include <net/genetlink.h> | 20 | #include <net/genetlink.h> |
21 | 21 | ||
22 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 22 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
23 | 23 | ||
24 | void genl_lock(void) | 24 | void genl_lock(void) |
25 | { | 25 | { |
26 | mutex_lock(&genl_mutex); | 26 | mutex_lock(&genl_mutex); |
27 | } | 27 | } |
28 | EXPORT_SYMBOL(genl_lock); | 28 | EXPORT_SYMBOL(genl_lock); |
29 | 29 | ||
30 | void genl_unlock(void) | 30 | void genl_unlock(void) |
31 | { | 31 | { |
32 | mutex_unlock(&genl_mutex); | 32 | mutex_unlock(&genl_mutex); |
33 | } | 33 | } |
34 | EXPORT_SYMBOL(genl_unlock); | 34 | EXPORT_SYMBOL(genl_unlock); |
35 | 35 | ||
36 | #define GENL_FAM_TAB_SIZE 16 | 36 | #define GENL_FAM_TAB_SIZE 16 |
37 | #define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1) | 37 | #define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1) |
38 | 38 | ||
39 | static struct list_head family_ht[GENL_FAM_TAB_SIZE]; | 39 | static struct list_head family_ht[GENL_FAM_TAB_SIZE]; |
40 | /* | 40 | /* |
41 | * Bitmap of multicast groups that are currently in use. | 41 | * Bitmap of multicast groups that are currently in use. |
42 | * | 42 | * |
43 | * To avoid an allocation at boot of just one unsigned long, | 43 | * To avoid an allocation at boot of just one unsigned long, |
44 | * declare it global instead. | 44 | * declare it global instead. |
45 | * Bit 0 is marked as already used since group 0 is invalid. | 45 | * Bit 0 is marked as already used since group 0 is invalid. |
46 | */ | 46 | */ |
47 | static unsigned long mc_group_start = 0x1; | 47 | static unsigned long mc_group_start = 0x1; |
48 | static unsigned long *mc_groups = &mc_group_start; | 48 | static unsigned long *mc_groups = &mc_group_start; |
49 | static unsigned long mc_groups_longs = 1; | 49 | static unsigned long mc_groups_longs = 1; |
50 | 50 | ||
51 | static int genl_ctrl_event(int event, void *data); | 51 | static int genl_ctrl_event(int event, void *data); |
52 | 52 | ||
53 | static inline unsigned int genl_family_hash(unsigned int id) | 53 | static inline unsigned int genl_family_hash(unsigned int id) |
54 | { | 54 | { |
55 | return id & GENL_FAM_TAB_MASK; | 55 | return id & GENL_FAM_TAB_MASK; |
56 | } | 56 | } |
57 | 57 | ||
58 | static inline struct list_head *genl_family_chain(unsigned int id) | 58 | static inline struct list_head *genl_family_chain(unsigned int id) |
59 | { | 59 | { |
60 | return &family_ht[genl_family_hash(id)]; | 60 | return &family_ht[genl_family_hash(id)]; |
61 | } | 61 | } |
62 | 62 | ||
63 | static struct genl_family *genl_family_find_byid(unsigned int id) | 63 | static struct genl_family *genl_family_find_byid(unsigned int id) |
64 | { | 64 | { |
65 | struct genl_family *f; | 65 | struct genl_family *f; |
66 | 66 | ||
67 | list_for_each_entry(f, genl_family_chain(id), family_list) | 67 | list_for_each_entry(f, genl_family_chain(id), family_list) |
68 | if (f->id == id) | 68 | if (f->id == id) |
69 | return f; | 69 | return f; |
70 | 70 | ||
71 | return NULL; | 71 | return NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | static struct genl_family *genl_family_find_byname(char *name) | 74 | static struct genl_family *genl_family_find_byname(char *name) |
75 | { | 75 | { |
76 | struct genl_family *f; | 76 | struct genl_family *f; |
77 | int i; | 77 | int i; |
78 | 78 | ||
79 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) | 79 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) |
80 | list_for_each_entry(f, genl_family_chain(i), family_list) | 80 | list_for_each_entry(f, genl_family_chain(i), family_list) |
81 | if (strcmp(f->name, name) == 0) | 81 | if (strcmp(f->name, name) == 0) |
82 | return f; | 82 | return f; |
83 | 83 | ||
84 | return NULL; | 84 | return NULL; |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) | 87 | static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) |
88 | { | 88 | { |
89 | struct genl_ops *ops; | 89 | struct genl_ops *ops; |
90 | 90 | ||
91 | list_for_each_entry(ops, &family->ops_list, ops_list) | 91 | list_for_each_entry(ops, &family->ops_list, ops_list) |
92 | if (ops->cmd == cmd) | 92 | if (ops->cmd == cmd) |
93 | return ops; | 93 | return ops; |
94 | 94 | ||
95 | return NULL; | 95 | return NULL; |
96 | } | 96 | } |
97 | 97 | ||
98 | /* Of course we are going to have problems once we hit | 98 | /* Of course we are going to have problems once we hit |
99 | * 2^16 alive types, but that can only happen by year 2K | 99 | * 2^16 alive types, but that can only happen by year 2K |
100 | */ | 100 | */ |
101 | static inline u16 genl_generate_id(void) | 101 | static inline u16 genl_generate_id(void) |
102 | { | 102 | { |
103 | static u16 id_gen_idx = GENL_MIN_ID; | 103 | static u16 id_gen_idx = GENL_MIN_ID; |
104 | int i; | 104 | int i; |
105 | 105 | ||
106 | for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) { | 106 | for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) { |
107 | if (!genl_family_find_byid(id_gen_idx)) | 107 | if (!genl_family_find_byid(id_gen_idx)) |
108 | return id_gen_idx; | 108 | return id_gen_idx; |
109 | if (++id_gen_idx > GENL_MAX_ID) | 109 | if (++id_gen_idx > GENL_MAX_ID) |
110 | id_gen_idx = GENL_MIN_ID; | 110 | id_gen_idx = GENL_MIN_ID; |
111 | } | 111 | } |
112 | 112 | ||
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static struct genl_multicast_group notify_grp; | 116 | static struct genl_multicast_group notify_grp; |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * genl_register_mc_group - register a multicast group | 119 | * genl_register_mc_group - register a multicast group |
120 | * | 120 | * |
121 | * Registers the specified multicast group and notifies userspace | 121 | * Registers the specified multicast group and notifies userspace |
122 | * about the new group. | 122 | * about the new group. |
123 | * | 123 | * |
124 | * Returns 0 on success or a negative error code. | 124 | * Returns 0 on success or a negative error code. |
125 | * | 125 | * |
126 | * @family: The generic netlink family the group shall be registered for. | 126 | * @family: The generic netlink family the group shall be registered for. |
127 | * @grp: The group to register, must have a name. | 127 | * @grp: The group to register, must have a name. |
128 | */ | 128 | */ |
129 | int genl_register_mc_group(struct genl_family *family, | 129 | int genl_register_mc_group(struct genl_family *family, |
130 | struct genl_multicast_group *grp) | 130 | struct genl_multicast_group *grp) |
131 | { | 131 | { |
132 | int id; | 132 | int id; |
133 | unsigned long *new_groups; | 133 | unsigned long *new_groups; |
134 | int err = 0; | 134 | int err = 0; |
135 | 135 | ||
136 | BUG_ON(grp->name[0] == '\0'); | 136 | BUG_ON(grp->name[0] == '\0'); |
137 | 137 | ||
138 | genl_lock(); | 138 | genl_lock(); |
139 | 139 | ||
140 | /* special-case our own group */ | 140 | /* special-case our own group */ |
141 | if (grp == ¬ify_grp) | 141 | if (grp == ¬ify_grp) |
142 | id = GENL_ID_CTRL; | 142 | id = GENL_ID_CTRL; |
143 | else | 143 | else |
144 | id = find_first_zero_bit(mc_groups, | 144 | id = find_first_zero_bit(mc_groups, |
145 | mc_groups_longs * BITS_PER_LONG); | 145 | mc_groups_longs * BITS_PER_LONG); |
146 | 146 | ||
147 | 147 | ||
148 | if (id >= mc_groups_longs * BITS_PER_LONG) { | 148 | if (id >= mc_groups_longs * BITS_PER_LONG) { |
149 | size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long); | 149 | size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long); |
150 | 150 | ||
151 | if (mc_groups == &mc_group_start) { | 151 | if (mc_groups == &mc_group_start) { |
152 | new_groups = kzalloc(nlen, GFP_KERNEL); | 152 | new_groups = kzalloc(nlen, GFP_KERNEL); |
153 | if (!new_groups) { | 153 | if (!new_groups) { |
154 | err = -ENOMEM; | 154 | err = -ENOMEM; |
155 | goto out; | 155 | goto out; |
156 | } | 156 | } |
157 | mc_groups = new_groups; | 157 | mc_groups = new_groups; |
158 | *mc_groups = mc_group_start; | 158 | *mc_groups = mc_group_start; |
159 | } else { | 159 | } else { |
160 | new_groups = krealloc(mc_groups, nlen, GFP_KERNEL); | 160 | new_groups = krealloc(mc_groups, nlen, GFP_KERNEL); |
161 | if (!new_groups) { | 161 | if (!new_groups) { |
162 | err = -ENOMEM; | 162 | err = -ENOMEM; |
163 | goto out; | 163 | goto out; |
164 | } | 164 | } |
165 | mc_groups = new_groups; | 165 | mc_groups = new_groups; |
166 | mc_groups[mc_groups_longs] = 0; | 166 | mc_groups[mc_groups_longs] = 0; |
167 | } | 167 | } |
168 | mc_groups_longs++; | 168 | mc_groups_longs++; |
169 | } | 169 | } |
170 | 170 | ||
171 | if (family->netnsok) { | 171 | if (family->netnsok) { |
172 | struct net *net; | 172 | struct net *net; |
173 | 173 | ||
174 | netlink_table_grab(); | 174 | netlink_table_grab(); |
175 | rcu_read_lock(); | 175 | rcu_read_lock(); |
176 | for_each_net_rcu(net) { | 176 | for_each_net_rcu(net) { |
177 | err = __netlink_change_ngroups(net->genl_sock, | 177 | err = __netlink_change_ngroups(net->genl_sock, |
178 | mc_groups_longs * BITS_PER_LONG); | 178 | mc_groups_longs * BITS_PER_LONG); |
179 | if (err) { | 179 | if (err) { |
180 | /* | 180 | /* |
181 | * No need to roll back, can only fail if | 181 | * No need to roll back, can only fail if |
182 | * memory allocation fails and then the | 182 | * memory allocation fails and then the |
183 | * number of _possible_ groups has been | 183 | * number of _possible_ groups has been |
184 | * increased on some sockets which is ok. | 184 | * increased on some sockets which is ok. |
185 | */ | 185 | */ |
186 | rcu_read_unlock(); | 186 | rcu_read_unlock(); |
187 | netlink_table_ungrab(); | 187 | netlink_table_ungrab(); |
188 | goto out; | 188 | goto out; |
189 | } | 189 | } |
190 | } | 190 | } |
191 | rcu_read_unlock(); | 191 | rcu_read_unlock(); |
192 | netlink_table_ungrab(); | 192 | netlink_table_ungrab(); |
193 | } else { | 193 | } else { |
194 | err = netlink_change_ngroups(init_net.genl_sock, | 194 | err = netlink_change_ngroups(init_net.genl_sock, |
195 | mc_groups_longs * BITS_PER_LONG); | 195 | mc_groups_longs * BITS_PER_LONG); |
196 | if (err) | 196 | if (err) |
197 | goto out; | 197 | goto out; |
198 | } | 198 | } |
199 | 199 | ||
200 | grp->id = id; | 200 | grp->id = id; |
201 | set_bit(id, mc_groups); | 201 | set_bit(id, mc_groups); |
202 | list_add_tail(&grp->list, &family->mcast_groups); | 202 | list_add_tail(&grp->list, &family->mcast_groups); |
203 | grp->family = family; | 203 | grp->family = family; |
204 | 204 | ||
205 | genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, grp); | 205 | genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, grp); |
206 | out: | 206 | out: |
207 | genl_unlock(); | 207 | genl_unlock(); |
208 | return err; | 208 | return err; |
209 | } | 209 | } |
210 | EXPORT_SYMBOL(genl_register_mc_group); | 210 | EXPORT_SYMBOL(genl_register_mc_group); |
211 | 211 | ||
212 | static void __genl_unregister_mc_group(struct genl_family *family, | 212 | static void __genl_unregister_mc_group(struct genl_family *family, |
213 | struct genl_multicast_group *grp) | 213 | struct genl_multicast_group *grp) |
214 | { | 214 | { |
215 | struct net *net; | 215 | struct net *net; |
216 | BUG_ON(grp->family != family); | 216 | BUG_ON(grp->family != family); |
217 | 217 | ||
218 | netlink_table_grab(); | 218 | netlink_table_grab(); |
219 | rcu_read_lock(); | 219 | rcu_read_lock(); |
220 | for_each_net_rcu(net) | 220 | for_each_net_rcu(net) |
221 | __netlink_clear_multicast_users(net->genl_sock, grp->id); | 221 | __netlink_clear_multicast_users(net->genl_sock, grp->id); |
222 | rcu_read_unlock(); | 222 | rcu_read_unlock(); |
223 | netlink_table_ungrab(); | 223 | netlink_table_ungrab(); |
224 | 224 | ||
225 | clear_bit(grp->id, mc_groups); | 225 | clear_bit(grp->id, mc_groups); |
226 | list_del(&grp->list); | 226 | list_del(&grp->list); |
227 | genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp); | 227 | genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp); |
228 | grp->id = 0; | 228 | grp->id = 0; |
229 | grp->family = NULL; | 229 | grp->family = NULL; |
230 | } | 230 | } |
231 | 231 | ||
232 | /** | 232 | /** |
233 | * genl_unregister_mc_group - unregister a multicast group | 233 | * genl_unregister_mc_group - unregister a multicast group |
234 | * | 234 | * |
235 | * Unregisters the specified multicast group and notifies userspace | 235 | * Unregisters the specified multicast group and notifies userspace |
236 | * about it. All current listeners on the group are removed. | 236 | * about it. All current listeners on the group are removed. |
237 | * | 237 | * |
238 | * Note: It is not necessary to unregister all multicast groups before | 238 | * Note: It is not necessary to unregister all multicast groups before |
239 | * unregistering the family, unregistering the family will cause | 239 | * unregistering the family, unregistering the family will cause |
240 | * all assigned multicast groups to be unregistered automatically. | 240 | * all assigned multicast groups to be unregistered automatically. |
241 | * | 241 | * |
242 | * @family: Generic netlink family the group belongs to. | 242 | * @family: Generic netlink family the group belongs to. |
243 | * @grp: The group to unregister, must have been registered successfully | 243 | * @grp: The group to unregister, must have been registered successfully |
244 | * previously. | 244 | * previously. |
245 | */ | 245 | */ |
246 | void genl_unregister_mc_group(struct genl_family *family, | 246 | void genl_unregister_mc_group(struct genl_family *family, |
247 | struct genl_multicast_group *grp) | 247 | struct genl_multicast_group *grp) |
248 | { | 248 | { |
249 | genl_lock(); | 249 | genl_lock(); |
250 | __genl_unregister_mc_group(family, grp); | 250 | __genl_unregister_mc_group(family, grp); |
251 | genl_unlock(); | 251 | genl_unlock(); |
252 | } | 252 | } |
253 | EXPORT_SYMBOL(genl_unregister_mc_group); | 253 | EXPORT_SYMBOL(genl_unregister_mc_group); |
254 | 254 | ||
255 | static void genl_unregister_mc_groups(struct genl_family *family) | 255 | static void genl_unregister_mc_groups(struct genl_family *family) |
256 | { | 256 | { |
257 | struct genl_multicast_group *grp, *tmp; | 257 | struct genl_multicast_group *grp, *tmp; |
258 | 258 | ||
259 | list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) | 259 | list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) |
260 | __genl_unregister_mc_group(family, grp); | 260 | __genl_unregister_mc_group(family, grp); |
261 | } | 261 | } |
262 | 262 | ||
263 | /** | 263 | /** |
264 | * genl_register_ops - register generic netlink operations | 264 | * genl_register_ops - register generic netlink operations |
265 | * @family: generic netlink family | 265 | * @family: generic netlink family |
266 | * @ops: operations to be registered | 266 | * @ops: operations to be registered |
267 | * | 267 | * |
268 | * Registers the specified operations and assigns them to the specified | 268 | * Registers the specified operations and assigns them to the specified |
269 | * family. Either a doit or dumpit callback must be specified or the | 269 | * family. Either a doit or dumpit callback must be specified or the |
270 | * operation will fail. Only one operation structure per command | 270 | * operation will fail. Only one operation structure per command |
271 | * identifier may be registered. | 271 | * identifier may be registered. |
272 | * | 272 | * |
273 | * See include/net/genetlink.h for more documenation on the operations | 273 | * See include/net/genetlink.h for more documenation on the operations |
274 | * structure. | 274 | * structure. |
275 | * | 275 | * |
276 | * Returns 0 on success or a negative error code. | 276 | * Returns 0 on success or a negative error code. |
277 | */ | 277 | */ |
278 | int genl_register_ops(struct genl_family *family, struct genl_ops *ops) | 278 | int genl_register_ops(struct genl_family *family, struct genl_ops *ops) |
279 | { | 279 | { |
280 | int err = -EINVAL; | 280 | int err = -EINVAL; |
281 | 281 | ||
282 | if (ops->dumpit == NULL && ops->doit == NULL) | 282 | if (ops->dumpit == NULL && ops->doit == NULL) |
283 | goto errout; | 283 | goto errout; |
284 | 284 | ||
285 | if (genl_get_cmd(ops->cmd, family)) { | 285 | if (genl_get_cmd(ops->cmd, family)) { |
286 | err = -EEXIST; | 286 | err = -EEXIST; |
287 | goto errout; | 287 | goto errout; |
288 | } | 288 | } |
289 | 289 | ||
290 | if (ops->dumpit) | 290 | if (ops->dumpit) |
291 | ops->flags |= GENL_CMD_CAP_DUMP; | 291 | ops->flags |= GENL_CMD_CAP_DUMP; |
292 | if (ops->doit) | 292 | if (ops->doit) |
293 | ops->flags |= GENL_CMD_CAP_DO; | 293 | ops->flags |= GENL_CMD_CAP_DO; |
294 | if (ops->policy) | 294 | if (ops->policy) |
295 | ops->flags |= GENL_CMD_CAP_HASPOL; | 295 | ops->flags |= GENL_CMD_CAP_HASPOL; |
296 | 296 | ||
297 | genl_lock(); | 297 | genl_lock(); |
298 | list_add_tail(&ops->ops_list, &family->ops_list); | 298 | list_add_tail(&ops->ops_list, &family->ops_list); |
299 | genl_unlock(); | 299 | genl_unlock(); |
300 | 300 | ||
301 | genl_ctrl_event(CTRL_CMD_NEWOPS, ops); | 301 | genl_ctrl_event(CTRL_CMD_NEWOPS, ops); |
302 | err = 0; | 302 | err = 0; |
303 | errout: | 303 | errout: |
304 | return err; | 304 | return err; |
305 | } | 305 | } |
306 | EXPORT_SYMBOL(genl_register_ops); | 306 | EXPORT_SYMBOL(genl_register_ops); |
307 | 307 | ||
308 | /** | 308 | /** |
309 | * genl_unregister_ops - unregister generic netlink operations | 309 | * genl_unregister_ops - unregister generic netlink operations |
310 | * @family: generic netlink family | 310 | * @family: generic netlink family |
311 | * @ops: operations to be unregistered | 311 | * @ops: operations to be unregistered |
312 | * | 312 | * |
313 | * Unregisters the specified operations and unassigns them from the | 313 | * Unregisters the specified operations and unassigns them from the |
314 | * specified family. The operation blocks until the current message | 314 | * specified family. The operation blocks until the current message |
315 | * processing has finished and doesn't start again until the | 315 | * processing has finished and doesn't start again until the |
316 | * unregister process has finished. | 316 | * unregister process has finished. |
317 | * | 317 | * |
318 | * Note: It is not necessary to unregister all operations before | 318 | * Note: It is not necessary to unregister all operations before |
319 | * unregistering the family, unregistering the family will cause | 319 | * unregistering the family, unregistering the family will cause |
320 | * all assigned operations to be unregistered automatically. | 320 | * all assigned operations to be unregistered automatically. |
321 | * | 321 | * |
322 | * Returns 0 on success or a negative error code. | 322 | * Returns 0 on success or a negative error code. |
323 | */ | 323 | */ |
324 | int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops) | 324 | int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops) |
325 | { | 325 | { |
326 | struct genl_ops *rc; | 326 | struct genl_ops *rc; |
327 | 327 | ||
328 | genl_lock(); | 328 | genl_lock(); |
329 | list_for_each_entry(rc, &family->ops_list, ops_list) { | 329 | list_for_each_entry(rc, &family->ops_list, ops_list) { |
330 | if (rc == ops) { | 330 | if (rc == ops) { |
331 | list_del(&ops->ops_list); | 331 | list_del(&ops->ops_list); |
332 | genl_unlock(); | 332 | genl_unlock(); |
333 | genl_ctrl_event(CTRL_CMD_DELOPS, ops); | 333 | genl_ctrl_event(CTRL_CMD_DELOPS, ops); |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | } | 336 | } |
337 | genl_unlock(); | 337 | genl_unlock(); |
338 | 338 | ||
339 | return -ENOENT; | 339 | return -ENOENT; |
340 | } | 340 | } |
341 | EXPORT_SYMBOL(genl_unregister_ops); | 341 | EXPORT_SYMBOL(genl_unregister_ops); |
342 | 342 | ||
343 | /** | 343 | /** |
344 | * genl_register_family - register a generic netlink family | 344 | * genl_register_family - register a generic netlink family |
345 | * @family: generic netlink family | 345 | * @family: generic netlink family |
346 | * | 346 | * |
347 | * Registers the specified family after validating it first. Only one | 347 | * Registers the specified family after validating it first. Only one |
348 | * family may be registered with the same family name or identifier. | 348 | * family may be registered with the same family name or identifier. |
349 | * The family id may equal GENL_ID_GENERATE causing an unique id to | 349 | * The family id may equal GENL_ID_GENERATE causing an unique id to |
350 | * be automatically generated and assigned. | 350 | * be automatically generated and assigned. |
351 | * | 351 | * |
352 | * Return 0 on success or a negative error code. | 352 | * Return 0 on success or a negative error code. |
353 | */ | 353 | */ |
354 | int genl_register_family(struct genl_family *family) | 354 | int genl_register_family(struct genl_family *family) |
355 | { | 355 | { |
356 | int err = -EINVAL; | 356 | int err = -EINVAL; |
357 | 357 | ||
358 | if (family->id && family->id < GENL_MIN_ID) | 358 | if (family->id && family->id < GENL_MIN_ID) |
359 | goto errout; | 359 | goto errout; |
360 | 360 | ||
361 | if (family->id > GENL_MAX_ID) | 361 | if (family->id > GENL_MAX_ID) |
362 | goto errout; | 362 | goto errout; |
363 | 363 | ||
364 | INIT_LIST_HEAD(&family->ops_list); | 364 | INIT_LIST_HEAD(&family->ops_list); |
365 | INIT_LIST_HEAD(&family->mcast_groups); | 365 | INIT_LIST_HEAD(&family->mcast_groups); |
366 | 366 | ||
367 | genl_lock(); | 367 | genl_lock(); |
368 | 368 | ||
369 | if (genl_family_find_byname(family->name)) { | 369 | if (genl_family_find_byname(family->name)) { |
370 | err = -EEXIST; | 370 | err = -EEXIST; |
371 | goto errout_locked; | 371 | goto errout_locked; |
372 | } | 372 | } |
373 | 373 | ||
374 | if (family->id == GENL_ID_GENERATE) { | 374 | if (family->id == GENL_ID_GENERATE) { |
375 | u16 newid = genl_generate_id(); | 375 | u16 newid = genl_generate_id(); |
376 | 376 | ||
377 | if (!newid) { | 377 | if (!newid) { |
378 | err = -ENOMEM; | 378 | err = -ENOMEM; |
379 | goto errout_locked; | 379 | goto errout_locked; |
380 | } | 380 | } |
381 | 381 | ||
382 | family->id = newid; | 382 | family->id = newid; |
383 | } else if (genl_family_find_byid(family->id)) { | 383 | } else if (genl_family_find_byid(family->id)) { |
384 | err = -EEXIST; | 384 | err = -EEXIST; |
385 | goto errout_locked; | 385 | goto errout_locked; |
386 | } | 386 | } |
387 | 387 | ||
388 | if (family->maxattr) { | 388 | if (family->maxattr) { |
389 | family->attrbuf = kmalloc((family->maxattr+1) * | 389 | family->attrbuf = kmalloc((family->maxattr+1) * |
390 | sizeof(struct nlattr *), GFP_KERNEL); | 390 | sizeof(struct nlattr *), GFP_KERNEL); |
391 | if (family->attrbuf == NULL) { | 391 | if (family->attrbuf == NULL) { |
392 | err = -ENOMEM; | 392 | err = -ENOMEM; |
393 | goto errout_locked; | 393 | goto errout_locked; |
394 | } | 394 | } |
395 | } else | 395 | } else |
396 | family->attrbuf = NULL; | 396 | family->attrbuf = NULL; |
397 | 397 | ||
398 | list_add_tail(&family->family_list, genl_family_chain(family->id)); | 398 | list_add_tail(&family->family_list, genl_family_chain(family->id)); |
399 | genl_unlock(); | 399 | genl_unlock(); |
400 | 400 | ||
401 | genl_ctrl_event(CTRL_CMD_NEWFAMILY, family); | 401 | genl_ctrl_event(CTRL_CMD_NEWFAMILY, family); |
402 | 402 | ||
403 | return 0; | 403 | return 0; |
404 | 404 | ||
405 | errout_locked: | 405 | errout_locked: |
406 | genl_unlock(); | 406 | genl_unlock(); |
407 | errout: | 407 | errout: |
408 | return err; | 408 | return err; |
409 | } | 409 | } |
410 | EXPORT_SYMBOL(genl_register_family); | 410 | EXPORT_SYMBOL(genl_register_family); |
411 | 411 | ||
412 | /** | 412 | /** |
413 | * genl_register_family_with_ops - register a generic netlink family | 413 | * genl_register_family_with_ops - register a generic netlink family |
414 | * @family: generic netlink family | 414 | * @family: generic netlink family |
415 | * @ops: operations to be registered | 415 | * @ops: operations to be registered |
416 | * @n_ops: number of elements to register | 416 | * @n_ops: number of elements to register |
417 | * | 417 | * |
418 | * Registers the specified family and operations from the specified table. | 418 | * Registers the specified family and operations from the specified table. |
419 | * Only one family may be registered with the same family name or identifier. | 419 | * Only one family may be registered with the same family name or identifier. |
420 | * | 420 | * |
421 | * The family id may equal GENL_ID_GENERATE causing an unique id to | 421 | * The family id may equal GENL_ID_GENERATE causing an unique id to |
422 | * be automatically generated and assigned. | 422 | * be automatically generated and assigned. |
423 | * | 423 | * |
424 | * Either a doit or dumpit callback must be specified for every registered | 424 | * Either a doit or dumpit callback must be specified for every registered |
425 | * operation or the function will fail. Only one operation structure per | 425 | * operation or the function will fail. Only one operation structure per |
426 | * command identifier may be registered. | 426 | * command identifier may be registered. |
427 | * | 427 | * |
428 | * See include/net/genetlink.h for more documenation on the operations | 428 | * See include/net/genetlink.h for more documenation on the operations |
429 | * structure. | 429 | * structure. |
430 | * | 430 | * |
431 | * This is equivalent to calling genl_register_family() followed by | 431 | * This is equivalent to calling genl_register_family() followed by |
432 | * genl_register_ops() for every operation entry in the table taking | 432 | * genl_register_ops() for every operation entry in the table taking |
433 | * care to unregister the family on error path. | 433 | * care to unregister the family on error path. |
434 | * | 434 | * |
435 | * Return 0 on success or a negative error code. | 435 | * Return 0 on success or a negative error code. |
436 | */ | 436 | */ |
437 | int genl_register_family_with_ops(struct genl_family *family, | 437 | int genl_register_family_with_ops(struct genl_family *family, |
438 | struct genl_ops *ops, size_t n_ops) | 438 | struct genl_ops *ops, size_t n_ops) |
439 | { | 439 | { |
440 | int err, i; | 440 | int err, i; |
441 | 441 | ||
442 | err = genl_register_family(family); | 442 | err = genl_register_family(family); |
443 | if (err) | 443 | if (err) |
444 | return err; | 444 | return err; |
445 | 445 | ||
446 | for (i = 0; i < n_ops; ++i, ++ops) { | 446 | for (i = 0; i < n_ops; ++i, ++ops) { |
447 | err = genl_register_ops(family, ops); | 447 | err = genl_register_ops(family, ops); |
448 | if (err) | 448 | if (err) |
449 | goto err_out; | 449 | goto err_out; |
450 | } | 450 | } |
451 | return 0; | 451 | return 0; |
452 | err_out: | 452 | err_out: |
453 | genl_unregister_family(family); | 453 | genl_unregister_family(family); |
454 | return err; | 454 | return err; |
455 | } | 455 | } |
456 | EXPORT_SYMBOL(genl_register_family_with_ops); | 456 | EXPORT_SYMBOL(genl_register_family_with_ops); |
457 | 457 | ||
458 | /** | 458 | /** |
459 | * genl_unregister_family - unregister generic netlink family | 459 | * genl_unregister_family - unregister generic netlink family |
460 | * @family: generic netlink family | 460 | * @family: generic netlink family |
461 | * | 461 | * |
462 | * Unregisters the specified family. | 462 | * Unregisters the specified family. |
463 | * | 463 | * |
464 | * Returns 0 on success or a negative error code. | 464 | * Returns 0 on success or a negative error code. |
465 | */ | 465 | */ |
466 | int genl_unregister_family(struct genl_family *family) | 466 | int genl_unregister_family(struct genl_family *family) |
467 | { | 467 | { |
468 | struct genl_family *rc; | 468 | struct genl_family *rc; |
469 | 469 | ||
470 | genl_lock(); | 470 | genl_lock(); |
471 | 471 | ||
472 | genl_unregister_mc_groups(family); | 472 | genl_unregister_mc_groups(family); |
473 | 473 | ||
474 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { | 474 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { |
475 | if (family->id != rc->id || strcmp(rc->name, family->name)) | 475 | if (family->id != rc->id || strcmp(rc->name, family->name)) |
476 | continue; | 476 | continue; |
477 | 477 | ||
478 | list_del(&rc->family_list); | 478 | list_del(&rc->family_list); |
479 | INIT_LIST_HEAD(&family->ops_list); | 479 | INIT_LIST_HEAD(&family->ops_list); |
480 | genl_unlock(); | 480 | genl_unlock(); |
481 | 481 | ||
482 | kfree(family->attrbuf); | 482 | kfree(family->attrbuf); |
483 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); | 483 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); |
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
486 | 486 | ||
487 | genl_unlock(); | 487 | genl_unlock(); |
488 | 488 | ||
489 | return -ENOENT; | 489 | return -ENOENT; |
490 | } | 490 | } |
491 | EXPORT_SYMBOL(genl_unregister_family); | 491 | EXPORT_SYMBOL(genl_unregister_family); |
492 | 492 | ||
493 | static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 493 | static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
494 | { | 494 | { |
495 | struct genl_ops *ops; | 495 | struct genl_ops *ops; |
496 | struct genl_family *family; | 496 | struct genl_family *family; |
497 | struct net *net = sock_net(skb->sk); | 497 | struct net *net = sock_net(skb->sk); |
498 | struct genl_info info; | 498 | struct genl_info info; |
499 | struct genlmsghdr *hdr = nlmsg_data(nlh); | 499 | struct genlmsghdr *hdr = nlmsg_data(nlh); |
500 | int hdrlen, err; | 500 | int hdrlen, err; |
501 | 501 | ||
502 | family = genl_family_find_byid(nlh->nlmsg_type); | 502 | family = genl_family_find_byid(nlh->nlmsg_type); |
503 | if (family == NULL) | 503 | if (family == NULL) |
504 | return -ENOENT; | 504 | return -ENOENT; |
505 | 505 | ||
506 | /* this family doesn't exist in this netns */ | 506 | /* this family doesn't exist in this netns */ |
507 | if (!family->netnsok && !net_eq(net, &init_net)) | 507 | if (!family->netnsok && !net_eq(net, &init_net)) |
508 | return -ENOENT; | 508 | return -ENOENT; |
509 | 509 | ||
510 | hdrlen = GENL_HDRLEN + family->hdrsize; | 510 | hdrlen = GENL_HDRLEN + family->hdrsize; |
511 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) | 511 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) |
512 | return -EINVAL; | 512 | return -EINVAL; |
513 | 513 | ||
514 | ops = genl_get_cmd(hdr->cmd, family); | 514 | ops = genl_get_cmd(hdr->cmd, family); |
515 | if (ops == NULL) | 515 | if (ops == NULL) |
516 | return -EOPNOTSUPP; | 516 | return -EOPNOTSUPP; |
517 | 517 | ||
518 | if ((ops->flags & GENL_ADMIN_PERM) && | 518 | if ((ops->flags & GENL_ADMIN_PERM) && |
519 | security_netlink_recv(skb, CAP_NET_ADMIN)) | 519 | !capable(CAP_NET_ADMIN)) |
520 | return -EPERM; | 520 | return -EPERM; |
521 | 521 | ||
522 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 522 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
523 | if (ops->dumpit == NULL) | 523 | if (ops->dumpit == NULL) |
524 | return -EOPNOTSUPP; | 524 | return -EOPNOTSUPP; |
525 | 525 | ||
526 | genl_unlock(); | 526 | genl_unlock(); |
527 | err = netlink_dump_start(net->genl_sock, skb, nlh, | 527 | err = netlink_dump_start(net->genl_sock, skb, nlh, |
528 | ops->dumpit, ops->done, 0); | 528 | ops->dumpit, ops->done, 0); |
529 | genl_lock(); | 529 | genl_lock(); |
530 | return err; | 530 | return err; |
531 | } | 531 | } |
532 | 532 | ||
533 | if (ops->doit == NULL) | 533 | if (ops->doit == NULL) |
534 | return -EOPNOTSUPP; | 534 | return -EOPNOTSUPP; |
535 | 535 | ||
536 | if (family->attrbuf) { | 536 | if (family->attrbuf) { |
537 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, | 537 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, |
538 | ops->policy); | 538 | ops->policy); |
539 | if (err < 0) | 539 | if (err < 0) |
540 | return err; | 540 | return err; |
541 | } | 541 | } |
542 | 542 | ||
543 | info.snd_seq = nlh->nlmsg_seq; | 543 | info.snd_seq = nlh->nlmsg_seq; |
544 | info.snd_pid = NETLINK_CB(skb).pid; | 544 | info.snd_pid = NETLINK_CB(skb).pid; |
545 | info.nlhdr = nlh; | 545 | info.nlhdr = nlh; |
546 | info.genlhdr = nlmsg_data(nlh); | 546 | info.genlhdr = nlmsg_data(nlh); |
547 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; | 547 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; |
548 | info.attrs = family->attrbuf; | 548 | info.attrs = family->attrbuf; |
549 | genl_info_net_set(&info, net); | 549 | genl_info_net_set(&info, net); |
550 | memset(&info.user_ptr, 0, sizeof(info.user_ptr)); | 550 | memset(&info.user_ptr, 0, sizeof(info.user_ptr)); |
551 | 551 | ||
552 | if (family->pre_doit) { | 552 | if (family->pre_doit) { |
553 | err = family->pre_doit(ops, skb, &info); | 553 | err = family->pre_doit(ops, skb, &info); |
554 | if (err) | 554 | if (err) |
555 | return err; | 555 | return err; |
556 | } | 556 | } |
557 | 557 | ||
558 | err = ops->doit(skb, &info); | 558 | err = ops->doit(skb, &info); |
559 | 559 | ||
560 | if (family->post_doit) | 560 | if (family->post_doit) |
561 | family->post_doit(ops, skb, &info); | 561 | family->post_doit(ops, skb, &info); |
562 | 562 | ||
563 | return err; | 563 | return err; |
564 | } | 564 | } |
565 | 565 | ||
566 | static void genl_rcv(struct sk_buff *skb) | 566 | static void genl_rcv(struct sk_buff *skb) |
567 | { | 567 | { |
568 | genl_lock(); | 568 | genl_lock(); |
569 | netlink_rcv_skb(skb, &genl_rcv_msg); | 569 | netlink_rcv_skb(skb, &genl_rcv_msg); |
570 | genl_unlock(); | 570 | genl_unlock(); |
571 | } | 571 | } |
572 | 572 | ||
573 | /************************************************************************** | 573 | /************************************************************************** |
574 | * Controller | 574 | * Controller |
575 | **************************************************************************/ | 575 | **************************************************************************/ |
576 | 576 | ||
577 | static struct genl_family genl_ctrl = { | 577 | static struct genl_family genl_ctrl = { |
578 | .id = GENL_ID_CTRL, | 578 | .id = GENL_ID_CTRL, |
579 | .name = "nlctrl", | 579 | .name = "nlctrl", |
580 | .version = 0x2, | 580 | .version = 0x2, |
581 | .maxattr = CTRL_ATTR_MAX, | 581 | .maxattr = CTRL_ATTR_MAX, |
582 | .netnsok = true, | 582 | .netnsok = true, |
583 | }; | 583 | }; |
584 | 584 | ||
585 | static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, | 585 | static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, |
586 | u32 flags, struct sk_buff *skb, u8 cmd) | 586 | u32 flags, struct sk_buff *skb, u8 cmd) |
587 | { | 587 | { |
588 | void *hdr; | 588 | void *hdr; |
589 | 589 | ||
590 | hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); | 590 | hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); |
591 | if (hdr == NULL) | 591 | if (hdr == NULL) |
592 | return -1; | 592 | return -1; |
593 | 593 | ||
594 | NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); | 594 | NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); |
595 | NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); | 595 | NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); |
596 | NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version); | 596 | NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version); |
597 | NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); | 597 | NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); |
598 | NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); | 598 | NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); |
599 | 599 | ||
600 | if (!list_empty(&family->ops_list)) { | 600 | if (!list_empty(&family->ops_list)) { |
601 | struct nlattr *nla_ops; | 601 | struct nlattr *nla_ops; |
602 | struct genl_ops *ops; | 602 | struct genl_ops *ops; |
603 | int idx = 1; | 603 | int idx = 1; |
604 | 604 | ||
605 | nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); | 605 | nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); |
606 | if (nla_ops == NULL) | 606 | if (nla_ops == NULL) |
607 | goto nla_put_failure; | 607 | goto nla_put_failure; |
608 | 608 | ||
609 | list_for_each_entry(ops, &family->ops_list, ops_list) { | 609 | list_for_each_entry(ops, &family->ops_list, ops_list) { |
610 | struct nlattr *nest; | 610 | struct nlattr *nest; |
611 | 611 | ||
612 | nest = nla_nest_start(skb, idx++); | 612 | nest = nla_nest_start(skb, idx++); |
613 | if (nest == NULL) | 613 | if (nest == NULL) |
614 | goto nla_put_failure; | 614 | goto nla_put_failure; |
615 | 615 | ||
616 | NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); | 616 | NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); |
617 | NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); | 617 | NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); |
618 | 618 | ||
619 | nla_nest_end(skb, nest); | 619 | nla_nest_end(skb, nest); |
620 | } | 620 | } |
621 | 621 | ||
622 | nla_nest_end(skb, nla_ops); | 622 | nla_nest_end(skb, nla_ops); |
623 | } | 623 | } |
624 | 624 | ||
625 | if (!list_empty(&family->mcast_groups)) { | 625 | if (!list_empty(&family->mcast_groups)) { |
626 | struct genl_multicast_group *grp; | 626 | struct genl_multicast_group *grp; |
627 | struct nlattr *nla_grps; | 627 | struct nlattr *nla_grps; |
628 | int idx = 1; | 628 | int idx = 1; |
629 | 629 | ||
630 | nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); | 630 | nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); |
631 | if (nla_grps == NULL) | 631 | if (nla_grps == NULL) |
632 | goto nla_put_failure; | 632 | goto nla_put_failure; |
633 | 633 | ||
634 | list_for_each_entry(grp, &family->mcast_groups, list) { | 634 | list_for_each_entry(grp, &family->mcast_groups, list) { |
635 | struct nlattr *nest; | 635 | struct nlattr *nest; |
636 | 636 | ||
637 | nest = nla_nest_start(skb, idx++); | 637 | nest = nla_nest_start(skb, idx++); |
638 | if (nest == NULL) | 638 | if (nest == NULL) |
639 | goto nla_put_failure; | 639 | goto nla_put_failure; |
640 | 640 | ||
641 | NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); | 641 | NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); |
642 | NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, | 642 | NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, |
643 | grp->name); | 643 | grp->name); |
644 | 644 | ||
645 | nla_nest_end(skb, nest); | 645 | nla_nest_end(skb, nest); |
646 | } | 646 | } |
647 | nla_nest_end(skb, nla_grps); | 647 | nla_nest_end(skb, nla_grps); |
648 | } | 648 | } |
649 | 649 | ||
650 | return genlmsg_end(skb, hdr); | 650 | return genlmsg_end(skb, hdr); |
651 | 651 | ||
652 | nla_put_failure: | 652 | nla_put_failure: |
653 | genlmsg_cancel(skb, hdr); | 653 | genlmsg_cancel(skb, hdr); |
654 | return -EMSGSIZE; | 654 | return -EMSGSIZE; |
655 | } | 655 | } |
656 | 656 | ||
657 | static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid, | 657 | static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid, |
658 | u32 seq, u32 flags, struct sk_buff *skb, | 658 | u32 seq, u32 flags, struct sk_buff *skb, |
659 | u8 cmd) | 659 | u8 cmd) |
660 | { | 660 | { |
661 | void *hdr; | 661 | void *hdr; |
662 | struct nlattr *nla_grps; | 662 | struct nlattr *nla_grps; |
663 | struct nlattr *nest; | 663 | struct nlattr *nest; |
664 | 664 | ||
665 | hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); | 665 | hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); |
666 | if (hdr == NULL) | 666 | if (hdr == NULL) |
667 | return -1; | 667 | return -1; |
668 | 668 | ||
669 | NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name); | 669 | NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name); |
670 | NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id); | 670 | NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id); |
671 | 671 | ||
672 | nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); | 672 | nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); |
673 | if (nla_grps == NULL) | 673 | if (nla_grps == NULL) |
674 | goto nla_put_failure; | 674 | goto nla_put_failure; |
675 | 675 | ||
676 | nest = nla_nest_start(skb, 1); | 676 | nest = nla_nest_start(skb, 1); |
677 | if (nest == NULL) | 677 | if (nest == NULL) |
678 | goto nla_put_failure; | 678 | goto nla_put_failure; |
679 | 679 | ||
680 | NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); | 680 | NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); |
681 | NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, | 681 | NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, |
682 | grp->name); | 682 | grp->name); |
683 | 683 | ||
684 | nla_nest_end(skb, nest); | 684 | nla_nest_end(skb, nest); |
685 | nla_nest_end(skb, nla_grps); | 685 | nla_nest_end(skb, nla_grps); |
686 | 686 | ||
687 | return genlmsg_end(skb, hdr); | 687 | return genlmsg_end(skb, hdr); |
688 | 688 | ||
689 | nla_put_failure: | 689 | nla_put_failure: |
690 | genlmsg_cancel(skb, hdr); | 690 | genlmsg_cancel(skb, hdr); |
691 | return -EMSGSIZE; | 691 | return -EMSGSIZE; |
692 | } | 692 | } |
693 | 693 | ||
694 | static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) | 694 | static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) |
695 | { | 695 | { |
696 | 696 | ||
697 | int i, n = 0; | 697 | int i, n = 0; |
698 | struct genl_family *rt; | 698 | struct genl_family *rt; |
699 | struct net *net = sock_net(skb->sk); | 699 | struct net *net = sock_net(skb->sk); |
700 | int chains_to_skip = cb->args[0]; | 700 | int chains_to_skip = cb->args[0]; |
701 | int fams_to_skip = cb->args[1]; | 701 | int fams_to_skip = cb->args[1]; |
702 | 702 | ||
703 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { | 703 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { |
704 | n = 0; | 704 | n = 0; |
705 | list_for_each_entry(rt, genl_family_chain(i), family_list) { | 705 | list_for_each_entry(rt, genl_family_chain(i), family_list) { |
706 | if (!rt->netnsok && !net_eq(net, &init_net)) | 706 | if (!rt->netnsok && !net_eq(net, &init_net)) |
707 | continue; | 707 | continue; |
708 | if (++n < fams_to_skip) | 708 | if (++n < fams_to_skip) |
709 | continue; | 709 | continue; |
710 | if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid, | 710 | if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid, |
711 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 711 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
712 | skb, CTRL_CMD_NEWFAMILY) < 0) | 712 | skb, CTRL_CMD_NEWFAMILY) < 0) |
713 | goto errout; | 713 | goto errout; |
714 | } | 714 | } |
715 | 715 | ||
716 | fams_to_skip = 0; | 716 | fams_to_skip = 0; |
717 | } | 717 | } |
718 | 718 | ||
719 | errout: | 719 | errout: |
720 | cb->args[0] = i; | 720 | cb->args[0] = i; |
721 | cb->args[1] = n; | 721 | cb->args[1] = n; |
722 | 722 | ||
723 | return skb->len; | 723 | return skb->len; |
724 | } | 724 | } |
725 | 725 | ||
726 | static struct sk_buff *ctrl_build_family_msg(struct genl_family *family, | 726 | static struct sk_buff *ctrl_build_family_msg(struct genl_family *family, |
727 | u32 pid, int seq, u8 cmd) | 727 | u32 pid, int seq, u8 cmd) |
728 | { | 728 | { |
729 | struct sk_buff *skb; | 729 | struct sk_buff *skb; |
730 | int err; | 730 | int err; |
731 | 731 | ||
732 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 732 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
733 | if (skb == NULL) | 733 | if (skb == NULL) |
734 | return ERR_PTR(-ENOBUFS); | 734 | return ERR_PTR(-ENOBUFS); |
735 | 735 | ||
736 | err = ctrl_fill_info(family, pid, seq, 0, skb, cmd); | 736 | err = ctrl_fill_info(family, pid, seq, 0, skb, cmd); |
737 | if (err < 0) { | 737 | if (err < 0) { |
738 | nlmsg_free(skb); | 738 | nlmsg_free(skb); |
739 | return ERR_PTR(err); | 739 | return ERR_PTR(err); |
740 | } | 740 | } |
741 | 741 | ||
742 | return skb; | 742 | return skb; |
743 | } | 743 | } |
744 | 744 | ||
745 | static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp, | 745 | static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp, |
746 | u32 pid, int seq, u8 cmd) | 746 | u32 pid, int seq, u8 cmd) |
747 | { | 747 | { |
748 | struct sk_buff *skb; | 748 | struct sk_buff *skb; |
749 | int err; | 749 | int err; |
750 | 750 | ||
751 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 751 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
752 | if (skb == NULL) | 752 | if (skb == NULL) |
753 | return ERR_PTR(-ENOBUFS); | 753 | return ERR_PTR(-ENOBUFS); |
754 | 754 | ||
755 | err = ctrl_fill_mcgrp_info(grp, pid, seq, 0, skb, cmd); | 755 | err = ctrl_fill_mcgrp_info(grp, pid, seq, 0, skb, cmd); |
756 | if (err < 0) { | 756 | if (err < 0) { |
757 | nlmsg_free(skb); | 757 | nlmsg_free(skb); |
758 | return ERR_PTR(err); | 758 | return ERR_PTR(err); |
759 | } | 759 | } |
760 | 760 | ||
761 | return skb; | 761 | return skb; |
762 | } | 762 | } |
763 | 763 | ||
764 | static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { | 764 | static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { |
765 | [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, | 765 | [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, |
766 | [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, | 766 | [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, |
767 | .len = GENL_NAMSIZ - 1 }, | 767 | .len = GENL_NAMSIZ - 1 }, |
768 | }; | 768 | }; |
769 | 769 | ||
770 | static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) | 770 | static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) |
771 | { | 771 | { |
772 | struct sk_buff *msg; | 772 | struct sk_buff *msg; |
773 | struct genl_family *res = NULL; | 773 | struct genl_family *res = NULL; |
774 | int err = -EINVAL; | 774 | int err = -EINVAL; |
775 | 775 | ||
776 | if (info->attrs[CTRL_ATTR_FAMILY_ID]) { | 776 | if (info->attrs[CTRL_ATTR_FAMILY_ID]) { |
777 | u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]); | 777 | u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]); |
778 | res = genl_family_find_byid(id); | 778 | res = genl_family_find_byid(id); |
779 | err = -ENOENT; | 779 | err = -ENOENT; |
780 | } | 780 | } |
781 | 781 | ||
782 | if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { | 782 | if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { |
783 | char *name; | 783 | char *name; |
784 | 784 | ||
785 | name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]); | 785 | name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]); |
786 | res = genl_family_find_byname(name); | 786 | res = genl_family_find_byname(name); |
787 | err = -ENOENT; | 787 | err = -ENOENT; |
788 | } | 788 | } |
789 | 789 | ||
790 | if (res == NULL) | 790 | if (res == NULL) |
791 | return err; | 791 | return err; |
792 | 792 | ||
793 | if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) { | 793 | if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) { |
794 | /* family doesn't exist here */ | 794 | /* family doesn't exist here */ |
795 | return -ENOENT; | 795 | return -ENOENT; |
796 | } | 796 | } |
797 | 797 | ||
798 | msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq, | 798 | msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq, |
799 | CTRL_CMD_NEWFAMILY); | 799 | CTRL_CMD_NEWFAMILY); |
800 | if (IS_ERR(msg)) | 800 | if (IS_ERR(msg)) |
801 | return PTR_ERR(msg); | 801 | return PTR_ERR(msg); |
802 | 802 | ||
803 | return genlmsg_reply(msg, info); | 803 | return genlmsg_reply(msg, info); |
804 | } | 804 | } |
805 | 805 | ||
806 | static int genl_ctrl_event(int event, void *data) | 806 | static int genl_ctrl_event(int event, void *data) |
807 | { | 807 | { |
808 | struct sk_buff *msg; | 808 | struct sk_buff *msg; |
809 | struct genl_family *family; | 809 | struct genl_family *family; |
810 | struct genl_multicast_group *grp; | 810 | struct genl_multicast_group *grp; |
811 | 811 | ||
812 | /* genl is still initialising */ | 812 | /* genl is still initialising */ |
813 | if (!init_net.genl_sock) | 813 | if (!init_net.genl_sock) |
814 | return 0; | 814 | return 0; |
815 | 815 | ||
816 | switch (event) { | 816 | switch (event) { |
817 | case CTRL_CMD_NEWFAMILY: | 817 | case CTRL_CMD_NEWFAMILY: |
818 | case CTRL_CMD_DELFAMILY: | 818 | case CTRL_CMD_DELFAMILY: |
819 | family = data; | 819 | family = data; |
820 | msg = ctrl_build_family_msg(family, 0, 0, event); | 820 | msg = ctrl_build_family_msg(family, 0, 0, event); |
821 | break; | 821 | break; |
822 | case CTRL_CMD_NEWMCAST_GRP: | 822 | case CTRL_CMD_NEWMCAST_GRP: |
823 | case CTRL_CMD_DELMCAST_GRP: | 823 | case CTRL_CMD_DELMCAST_GRP: |
824 | grp = data; | 824 | grp = data; |
825 | family = grp->family; | 825 | family = grp->family; |
826 | msg = ctrl_build_mcgrp_msg(data, 0, 0, event); | 826 | msg = ctrl_build_mcgrp_msg(data, 0, 0, event); |
827 | break; | 827 | break; |
828 | default: | 828 | default: |
829 | return -EINVAL; | 829 | return -EINVAL; |
830 | } | 830 | } |
831 | 831 | ||
832 | if (IS_ERR(msg)) | 832 | if (IS_ERR(msg)) |
833 | return PTR_ERR(msg); | 833 | return PTR_ERR(msg); |
834 | 834 | ||
835 | if (!family->netnsok) { | 835 | if (!family->netnsok) { |
836 | genlmsg_multicast_netns(&init_net, msg, 0, | 836 | genlmsg_multicast_netns(&init_net, msg, 0, |
837 | GENL_ID_CTRL, GFP_KERNEL); | 837 | GENL_ID_CTRL, GFP_KERNEL); |
838 | } else { | 838 | } else { |
839 | rcu_read_lock(); | 839 | rcu_read_lock(); |
840 | genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC); | 840 | genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC); |
841 | rcu_read_unlock(); | 841 | rcu_read_unlock(); |
842 | } | 842 | } |
843 | 843 | ||
844 | return 0; | 844 | return 0; |
845 | } | 845 | } |
846 | 846 | ||
847 | static struct genl_ops genl_ctrl_ops = { | 847 | static struct genl_ops genl_ctrl_ops = { |
848 | .cmd = CTRL_CMD_GETFAMILY, | 848 | .cmd = CTRL_CMD_GETFAMILY, |
849 | .doit = ctrl_getfamily, | 849 | .doit = ctrl_getfamily, |
850 | .dumpit = ctrl_dumpfamily, | 850 | .dumpit = ctrl_dumpfamily, |
851 | .policy = ctrl_policy, | 851 | .policy = ctrl_policy, |
852 | }; | 852 | }; |
853 | 853 | ||
854 | static struct genl_multicast_group notify_grp = { | 854 | static struct genl_multicast_group notify_grp = { |
855 | .name = "notify", | 855 | .name = "notify", |
856 | }; | 856 | }; |
857 | 857 | ||
858 | static int __net_init genl_pernet_init(struct net *net) | 858 | static int __net_init genl_pernet_init(struct net *net) |
859 | { | 859 | { |
860 | /* we'll bump the group number right afterwards */ | 860 | /* we'll bump the group number right afterwards */ |
861 | net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0, | 861 | net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0, |
862 | genl_rcv, &genl_mutex, | 862 | genl_rcv, &genl_mutex, |
863 | THIS_MODULE); | 863 | THIS_MODULE); |
864 | 864 | ||
865 | if (!net->genl_sock && net_eq(net, &init_net)) | 865 | if (!net->genl_sock && net_eq(net, &init_net)) |
866 | panic("GENL: Cannot initialize generic netlink\n"); | 866 | panic("GENL: Cannot initialize generic netlink\n"); |
867 | 867 | ||
868 | if (!net->genl_sock) | 868 | if (!net->genl_sock) |
869 | return -ENOMEM; | 869 | return -ENOMEM; |
870 | 870 | ||
871 | return 0; | 871 | return 0; |
872 | } | 872 | } |
873 | 873 | ||
874 | static void __net_exit genl_pernet_exit(struct net *net) | 874 | static void __net_exit genl_pernet_exit(struct net *net) |
875 | { | 875 | { |
876 | netlink_kernel_release(net->genl_sock); | 876 | netlink_kernel_release(net->genl_sock); |
877 | net->genl_sock = NULL; | 877 | net->genl_sock = NULL; |
878 | } | 878 | } |
879 | 879 | ||
880 | static struct pernet_operations genl_pernet_ops = { | 880 | static struct pernet_operations genl_pernet_ops = { |
881 | .init = genl_pernet_init, | 881 | .init = genl_pernet_init, |
882 | .exit = genl_pernet_exit, | 882 | .exit = genl_pernet_exit, |
883 | }; | 883 | }; |
884 | 884 | ||
885 | static int __init genl_init(void) | 885 | static int __init genl_init(void) |
886 | { | 886 | { |
887 | int i, err; | 887 | int i, err; |
888 | 888 | ||
889 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) | 889 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) |
890 | INIT_LIST_HEAD(&family_ht[i]); | 890 | INIT_LIST_HEAD(&family_ht[i]); |
891 | 891 | ||
892 | err = genl_register_family_with_ops(&genl_ctrl, &genl_ctrl_ops, 1); | 892 | err = genl_register_family_with_ops(&genl_ctrl, &genl_ctrl_ops, 1); |
893 | if (err < 0) | 893 | if (err < 0) |
894 | goto problem; | 894 | goto problem; |
895 | 895 | ||
896 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); | 896 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); |
897 | 897 | ||
898 | err = register_pernet_subsys(&genl_pernet_ops); | 898 | err = register_pernet_subsys(&genl_pernet_ops); |
899 | if (err) | 899 | if (err) |
900 | goto problem; | 900 | goto problem; |
901 | 901 | ||
902 | err = genl_register_mc_group(&genl_ctrl, ¬ify_grp); | 902 | err = genl_register_mc_group(&genl_ctrl, ¬ify_grp); |
903 | if (err < 0) | 903 | if (err < 0) |
904 | goto problem; | 904 | goto problem; |
905 | 905 | ||
906 | return 0; | 906 | return 0; |
907 | 907 | ||
908 | problem: | 908 | problem: |
909 | panic("GENL: Cannot register controller: %d\n", err); | 909 | panic("GENL: Cannot register controller: %d\n", err); |
910 | } | 910 | } |
911 | 911 | ||
912 | subsys_initcall(genl_init); | 912 | subsys_initcall(genl_init); |
913 | 913 | ||
914 | static int genlmsg_mcast(struct sk_buff *skb, u32 pid, unsigned long group, | 914 | static int genlmsg_mcast(struct sk_buff *skb, u32 pid, unsigned long group, |
915 | gfp_t flags) | 915 | gfp_t flags) |
916 | { | 916 | { |
917 | struct sk_buff *tmp; | 917 | struct sk_buff *tmp; |
918 | struct net *net, *prev = NULL; | 918 | struct net *net, *prev = NULL; |
919 | int err; | 919 | int err; |
920 | 920 | ||
921 | for_each_net_rcu(net) { | 921 | for_each_net_rcu(net) { |
922 | if (prev) { | 922 | if (prev) { |
923 | tmp = skb_clone(skb, flags); | 923 | tmp = skb_clone(skb, flags); |
924 | if (!tmp) { | 924 | if (!tmp) { |
925 | err = -ENOMEM; | 925 | err = -ENOMEM; |
926 | goto error; | 926 | goto error; |
927 | } | 927 | } |
928 | err = nlmsg_multicast(prev->genl_sock, tmp, | 928 | err = nlmsg_multicast(prev->genl_sock, tmp, |
929 | pid, group, flags); | 929 | pid, group, flags); |
930 | if (err) | 930 | if (err) |
931 | goto error; | 931 | goto error; |
932 | } | 932 | } |
933 | 933 | ||
934 | prev = net; | 934 | prev = net; |
935 | } | 935 | } |
936 | 936 | ||
937 | return nlmsg_multicast(prev->genl_sock, skb, pid, group, flags); | 937 | return nlmsg_multicast(prev->genl_sock, skb, pid, group, flags); |
938 | error: | 938 | error: |
939 | kfree_skb(skb); | 939 | kfree_skb(skb); |
940 | return err; | 940 | return err; |
941 | } | 941 | } |
942 | 942 | ||
943 | int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid, unsigned int group, | 943 | int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid, unsigned int group, |
944 | gfp_t flags) | 944 | gfp_t flags) |
945 | { | 945 | { |
946 | return genlmsg_mcast(skb, pid, group, flags); | 946 | return genlmsg_mcast(skb, pid, group, flags); |
947 | } | 947 | } |
948 | EXPORT_SYMBOL(genlmsg_multicast_allns); | 948 | EXPORT_SYMBOL(genlmsg_multicast_allns); |
949 | 949 |
net/xfrm/xfrm_user.c
1 | /* xfrm_user.c: User interface to configure xfrm engine. | 1 | /* xfrm_user.c: User interface to configure xfrm engine. |
2 | * | 2 | * |
3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) |
4 | * | 4 | * |
5 | * Changes: | 5 | * Changes: |
6 | * Mitsuru KANDA @USAGI | 6 | * Mitsuru KANDA @USAGI |
7 | * Kazunori MIYAZAWA @USAGI | 7 | * Kazunori MIYAZAWA @USAGI |
8 | * Kunihiro Ishiguro <kunihiro@ipinfusion.com> | 8 | * Kunihiro Ishiguro <kunihiro@ipinfusion.com> |
9 | * IPv6 support | 9 | * IPv6 support |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/net.h> | 20 | #include <linux/net.h> |
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/pfkeyv2.h> | 22 | #include <linux/pfkeyv2.h> |
23 | #include <linux/ipsec.h> | 23 | #include <linux/ipsec.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/security.h> | 25 | #include <linux/security.h> |
26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
27 | #include <net/xfrm.h> | 27 | #include <net/xfrm.h> |
28 | #include <net/netlink.h> | 28 | #include <net/netlink.h> |
29 | #include <net/ah.h> | 29 | #include <net/ah.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 31 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | static inline int aead_len(struct xfrm_algo_aead *alg) | 35 | static inline int aead_len(struct xfrm_algo_aead *alg) |
36 | { | 36 | { |
37 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); | 37 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); |
38 | } | 38 | } |
39 | 39 | ||
40 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) | 40 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) |
41 | { | 41 | { |
42 | struct nlattr *rt = attrs[type]; | 42 | struct nlattr *rt = attrs[type]; |
43 | struct xfrm_algo *algp; | 43 | struct xfrm_algo *algp; |
44 | 44 | ||
45 | if (!rt) | 45 | if (!rt) |
46 | return 0; | 46 | return 0; |
47 | 47 | ||
48 | algp = nla_data(rt); | 48 | algp = nla_data(rt); |
49 | if (nla_len(rt) < xfrm_alg_len(algp)) | 49 | if (nla_len(rt) < xfrm_alg_len(algp)) |
50 | return -EINVAL; | 50 | return -EINVAL; |
51 | 51 | ||
52 | switch (type) { | 52 | switch (type) { |
53 | case XFRMA_ALG_AUTH: | 53 | case XFRMA_ALG_AUTH: |
54 | case XFRMA_ALG_CRYPT: | 54 | case XFRMA_ALG_CRYPT: |
55 | case XFRMA_ALG_COMP: | 55 | case XFRMA_ALG_COMP: |
56 | break; | 56 | break; |
57 | 57 | ||
58 | default: | 58 | default: |
59 | return -EINVAL; | 59 | return -EINVAL; |
60 | } | 60 | } |
61 | 61 | ||
62 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; | 62 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; |
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int verify_auth_trunc(struct nlattr **attrs) | 66 | static int verify_auth_trunc(struct nlattr **attrs) |
67 | { | 67 | { |
68 | struct nlattr *rt = attrs[XFRMA_ALG_AUTH_TRUNC]; | 68 | struct nlattr *rt = attrs[XFRMA_ALG_AUTH_TRUNC]; |
69 | struct xfrm_algo_auth *algp; | 69 | struct xfrm_algo_auth *algp; |
70 | 70 | ||
71 | if (!rt) | 71 | if (!rt) |
72 | return 0; | 72 | return 0; |
73 | 73 | ||
74 | algp = nla_data(rt); | 74 | algp = nla_data(rt); |
75 | if (nla_len(rt) < xfrm_alg_auth_len(algp)) | 75 | if (nla_len(rt) < xfrm_alg_auth_len(algp)) |
76 | return -EINVAL; | 76 | return -EINVAL; |
77 | 77 | ||
78 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; | 78 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; |
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int verify_aead(struct nlattr **attrs) | 82 | static int verify_aead(struct nlattr **attrs) |
83 | { | 83 | { |
84 | struct nlattr *rt = attrs[XFRMA_ALG_AEAD]; | 84 | struct nlattr *rt = attrs[XFRMA_ALG_AEAD]; |
85 | struct xfrm_algo_aead *algp; | 85 | struct xfrm_algo_aead *algp; |
86 | 86 | ||
87 | if (!rt) | 87 | if (!rt) |
88 | return 0; | 88 | return 0; |
89 | 89 | ||
90 | algp = nla_data(rt); | 90 | algp = nla_data(rt); |
91 | if (nla_len(rt) < aead_len(algp)) | 91 | if (nla_len(rt) < aead_len(algp)) |
92 | return -EINVAL; | 92 | return -EINVAL; |
93 | 93 | ||
94 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; | 94 | algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; |
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
97 | 97 | ||
98 | static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, | 98 | static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, |
99 | xfrm_address_t **addrp) | 99 | xfrm_address_t **addrp) |
100 | { | 100 | { |
101 | struct nlattr *rt = attrs[type]; | 101 | struct nlattr *rt = attrs[type]; |
102 | 102 | ||
103 | if (rt && addrp) | 103 | if (rt && addrp) |
104 | *addrp = nla_data(rt); | 104 | *addrp = nla_data(rt); |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline int verify_sec_ctx_len(struct nlattr **attrs) | 107 | static inline int verify_sec_ctx_len(struct nlattr **attrs) |
108 | { | 108 | { |
109 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 109 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
110 | struct xfrm_user_sec_ctx *uctx; | 110 | struct xfrm_user_sec_ctx *uctx; |
111 | 111 | ||
112 | if (!rt) | 112 | if (!rt) |
113 | return 0; | 113 | return 0; |
114 | 114 | ||
115 | uctx = nla_data(rt); | 115 | uctx = nla_data(rt); |
116 | if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) | 116 | if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline int verify_replay(struct xfrm_usersa_info *p, | 122 | static inline int verify_replay(struct xfrm_usersa_info *p, |
123 | struct nlattr **attrs) | 123 | struct nlattr **attrs) |
124 | { | 124 | { |
125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; | 125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; |
126 | 126 | ||
127 | if ((p->flags & XFRM_STATE_ESN) && !rt) | 127 | if ((p->flags & XFRM_STATE_ESN) && !rt) |
128 | return -EINVAL; | 128 | return -EINVAL; |
129 | 129 | ||
130 | if (!rt) | 130 | if (!rt) |
131 | return 0; | 131 | return 0; |
132 | 132 | ||
133 | if (p->id.proto != IPPROTO_ESP) | 133 | if (p->id.proto != IPPROTO_ESP) |
134 | return -EINVAL; | 134 | return -EINVAL; |
135 | 135 | ||
136 | if (p->replay_window != 0) | 136 | if (p->replay_window != 0) |
137 | return -EINVAL; | 137 | return -EINVAL; |
138 | 138 | ||
139 | return 0; | 139 | return 0; |
140 | } | 140 | } |
141 | 141 | ||
142 | static int verify_newsa_info(struct xfrm_usersa_info *p, | 142 | static int verify_newsa_info(struct xfrm_usersa_info *p, |
143 | struct nlattr **attrs) | 143 | struct nlattr **attrs) |
144 | { | 144 | { |
145 | int err; | 145 | int err; |
146 | 146 | ||
147 | err = -EINVAL; | 147 | err = -EINVAL; |
148 | switch (p->family) { | 148 | switch (p->family) { |
149 | case AF_INET: | 149 | case AF_INET: |
150 | break; | 150 | break; |
151 | 151 | ||
152 | case AF_INET6: | 152 | case AF_INET6: |
153 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 153 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
154 | break; | 154 | break; |
155 | #else | 155 | #else |
156 | err = -EAFNOSUPPORT; | 156 | err = -EAFNOSUPPORT; |
157 | goto out; | 157 | goto out; |
158 | #endif | 158 | #endif |
159 | 159 | ||
160 | default: | 160 | default: |
161 | goto out; | 161 | goto out; |
162 | } | 162 | } |
163 | 163 | ||
164 | err = -EINVAL; | 164 | err = -EINVAL; |
165 | switch (p->id.proto) { | 165 | switch (p->id.proto) { |
166 | case IPPROTO_AH: | 166 | case IPPROTO_AH: |
167 | if ((!attrs[XFRMA_ALG_AUTH] && | 167 | if ((!attrs[XFRMA_ALG_AUTH] && |
168 | !attrs[XFRMA_ALG_AUTH_TRUNC]) || | 168 | !attrs[XFRMA_ALG_AUTH_TRUNC]) || |
169 | attrs[XFRMA_ALG_AEAD] || | 169 | attrs[XFRMA_ALG_AEAD] || |
170 | attrs[XFRMA_ALG_CRYPT] || | 170 | attrs[XFRMA_ALG_CRYPT] || |
171 | attrs[XFRMA_ALG_COMP] || | 171 | attrs[XFRMA_ALG_COMP] || |
172 | attrs[XFRMA_TFCPAD]) | 172 | attrs[XFRMA_TFCPAD]) |
173 | goto out; | 173 | goto out; |
174 | break; | 174 | break; |
175 | 175 | ||
176 | case IPPROTO_ESP: | 176 | case IPPROTO_ESP: |
177 | if (attrs[XFRMA_ALG_COMP]) | 177 | if (attrs[XFRMA_ALG_COMP]) |
178 | goto out; | 178 | goto out; |
179 | if (!attrs[XFRMA_ALG_AUTH] && | 179 | if (!attrs[XFRMA_ALG_AUTH] && |
180 | !attrs[XFRMA_ALG_AUTH_TRUNC] && | 180 | !attrs[XFRMA_ALG_AUTH_TRUNC] && |
181 | !attrs[XFRMA_ALG_CRYPT] && | 181 | !attrs[XFRMA_ALG_CRYPT] && |
182 | !attrs[XFRMA_ALG_AEAD]) | 182 | !attrs[XFRMA_ALG_AEAD]) |
183 | goto out; | 183 | goto out; |
184 | if ((attrs[XFRMA_ALG_AUTH] || | 184 | if ((attrs[XFRMA_ALG_AUTH] || |
185 | attrs[XFRMA_ALG_AUTH_TRUNC] || | 185 | attrs[XFRMA_ALG_AUTH_TRUNC] || |
186 | attrs[XFRMA_ALG_CRYPT]) && | 186 | attrs[XFRMA_ALG_CRYPT]) && |
187 | attrs[XFRMA_ALG_AEAD]) | 187 | attrs[XFRMA_ALG_AEAD]) |
188 | goto out; | 188 | goto out; |
189 | if (attrs[XFRMA_TFCPAD] && | 189 | if (attrs[XFRMA_TFCPAD] && |
190 | p->mode != XFRM_MODE_TUNNEL) | 190 | p->mode != XFRM_MODE_TUNNEL) |
191 | goto out; | 191 | goto out; |
192 | break; | 192 | break; |
193 | 193 | ||
194 | case IPPROTO_COMP: | 194 | case IPPROTO_COMP: |
195 | if (!attrs[XFRMA_ALG_COMP] || | 195 | if (!attrs[XFRMA_ALG_COMP] || |
196 | attrs[XFRMA_ALG_AEAD] || | 196 | attrs[XFRMA_ALG_AEAD] || |
197 | attrs[XFRMA_ALG_AUTH] || | 197 | attrs[XFRMA_ALG_AUTH] || |
198 | attrs[XFRMA_ALG_AUTH_TRUNC] || | 198 | attrs[XFRMA_ALG_AUTH_TRUNC] || |
199 | attrs[XFRMA_ALG_CRYPT] || | 199 | attrs[XFRMA_ALG_CRYPT] || |
200 | attrs[XFRMA_TFCPAD]) | 200 | attrs[XFRMA_TFCPAD]) |
201 | goto out; | 201 | goto out; |
202 | break; | 202 | break; |
203 | 203 | ||
204 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 204 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
205 | case IPPROTO_DSTOPTS: | 205 | case IPPROTO_DSTOPTS: |
206 | case IPPROTO_ROUTING: | 206 | case IPPROTO_ROUTING: |
207 | if (attrs[XFRMA_ALG_COMP] || | 207 | if (attrs[XFRMA_ALG_COMP] || |
208 | attrs[XFRMA_ALG_AUTH] || | 208 | attrs[XFRMA_ALG_AUTH] || |
209 | attrs[XFRMA_ALG_AUTH_TRUNC] || | 209 | attrs[XFRMA_ALG_AUTH_TRUNC] || |
210 | attrs[XFRMA_ALG_AEAD] || | 210 | attrs[XFRMA_ALG_AEAD] || |
211 | attrs[XFRMA_ALG_CRYPT] || | 211 | attrs[XFRMA_ALG_CRYPT] || |
212 | attrs[XFRMA_ENCAP] || | 212 | attrs[XFRMA_ENCAP] || |
213 | attrs[XFRMA_SEC_CTX] || | 213 | attrs[XFRMA_SEC_CTX] || |
214 | attrs[XFRMA_TFCPAD] || | 214 | attrs[XFRMA_TFCPAD] || |
215 | !attrs[XFRMA_COADDR]) | 215 | !attrs[XFRMA_COADDR]) |
216 | goto out; | 216 | goto out; |
217 | break; | 217 | break; |
218 | #endif | 218 | #endif |
219 | 219 | ||
220 | default: | 220 | default: |
221 | goto out; | 221 | goto out; |
222 | } | 222 | } |
223 | 223 | ||
224 | if ((err = verify_aead(attrs))) | 224 | if ((err = verify_aead(attrs))) |
225 | goto out; | 225 | goto out; |
226 | if ((err = verify_auth_trunc(attrs))) | 226 | if ((err = verify_auth_trunc(attrs))) |
227 | goto out; | 227 | goto out; |
228 | if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH))) | 228 | if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH))) |
229 | goto out; | 229 | goto out; |
230 | if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT))) | 230 | if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT))) |
231 | goto out; | 231 | goto out; |
232 | if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP))) | 232 | if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP))) |
233 | goto out; | 233 | goto out; |
234 | if ((err = verify_sec_ctx_len(attrs))) | 234 | if ((err = verify_sec_ctx_len(attrs))) |
235 | goto out; | 235 | goto out; |
236 | if ((err = verify_replay(p, attrs))) | 236 | if ((err = verify_replay(p, attrs))) |
237 | goto out; | 237 | goto out; |
238 | 238 | ||
239 | err = -EINVAL; | 239 | err = -EINVAL; |
240 | switch (p->mode) { | 240 | switch (p->mode) { |
241 | case XFRM_MODE_TRANSPORT: | 241 | case XFRM_MODE_TRANSPORT: |
242 | case XFRM_MODE_TUNNEL: | 242 | case XFRM_MODE_TUNNEL: |
243 | case XFRM_MODE_ROUTEOPTIMIZATION: | 243 | case XFRM_MODE_ROUTEOPTIMIZATION: |
244 | case XFRM_MODE_BEET: | 244 | case XFRM_MODE_BEET: |
245 | break; | 245 | break; |
246 | 246 | ||
247 | default: | 247 | default: |
248 | goto out; | 248 | goto out; |
249 | } | 249 | } |
250 | 250 | ||
251 | err = 0; | 251 | err = 0; |
252 | 252 | ||
253 | out: | 253 | out: |
254 | return err; | 254 | return err; |
255 | } | 255 | } |
256 | 256 | ||
257 | static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, | 257 | static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, |
258 | struct xfrm_algo_desc *(*get_byname)(const char *, int), | 258 | struct xfrm_algo_desc *(*get_byname)(const char *, int), |
259 | struct nlattr *rta) | 259 | struct nlattr *rta) |
260 | { | 260 | { |
261 | struct xfrm_algo *p, *ualg; | 261 | struct xfrm_algo *p, *ualg; |
262 | struct xfrm_algo_desc *algo; | 262 | struct xfrm_algo_desc *algo; |
263 | 263 | ||
264 | if (!rta) | 264 | if (!rta) |
265 | return 0; | 265 | return 0; |
266 | 266 | ||
267 | ualg = nla_data(rta); | 267 | ualg = nla_data(rta); |
268 | 268 | ||
269 | algo = get_byname(ualg->alg_name, 1); | 269 | algo = get_byname(ualg->alg_name, 1); |
270 | if (!algo) | 270 | if (!algo) |
271 | return -ENOSYS; | 271 | return -ENOSYS; |
272 | *props = algo->desc.sadb_alg_id; | 272 | *props = algo->desc.sadb_alg_id; |
273 | 273 | ||
274 | p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL); | 274 | p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL); |
275 | if (!p) | 275 | if (!p) |
276 | return -ENOMEM; | 276 | return -ENOMEM; |
277 | 277 | ||
278 | strcpy(p->alg_name, algo->name); | 278 | strcpy(p->alg_name, algo->name); |
279 | *algpp = p; | 279 | *algpp = p; |
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int attach_auth(struct xfrm_algo_auth **algpp, u8 *props, | 283 | static int attach_auth(struct xfrm_algo_auth **algpp, u8 *props, |
284 | struct nlattr *rta) | 284 | struct nlattr *rta) |
285 | { | 285 | { |
286 | struct xfrm_algo *ualg; | 286 | struct xfrm_algo *ualg; |
287 | struct xfrm_algo_auth *p; | 287 | struct xfrm_algo_auth *p; |
288 | struct xfrm_algo_desc *algo; | 288 | struct xfrm_algo_desc *algo; |
289 | 289 | ||
290 | if (!rta) | 290 | if (!rta) |
291 | return 0; | 291 | return 0; |
292 | 292 | ||
293 | ualg = nla_data(rta); | 293 | ualg = nla_data(rta); |
294 | 294 | ||
295 | algo = xfrm_aalg_get_byname(ualg->alg_name, 1); | 295 | algo = xfrm_aalg_get_byname(ualg->alg_name, 1); |
296 | if (!algo) | 296 | if (!algo) |
297 | return -ENOSYS; | 297 | return -ENOSYS; |
298 | *props = algo->desc.sadb_alg_id; | 298 | *props = algo->desc.sadb_alg_id; |
299 | 299 | ||
300 | p = kmalloc(sizeof(*p) + (ualg->alg_key_len + 7) / 8, GFP_KERNEL); | 300 | p = kmalloc(sizeof(*p) + (ualg->alg_key_len + 7) / 8, GFP_KERNEL); |
301 | if (!p) | 301 | if (!p) |
302 | return -ENOMEM; | 302 | return -ENOMEM; |
303 | 303 | ||
304 | strcpy(p->alg_name, algo->name); | 304 | strcpy(p->alg_name, algo->name); |
305 | p->alg_key_len = ualg->alg_key_len; | 305 | p->alg_key_len = ualg->alg_key_len; |
306 | p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; | 306 | p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; |
307 | memcpy(p->alg_key, ualg->alg_key, (ualg->alg_key_len + 7) / 8); | 307 | memcpy(p->alg_key, ualg->alg_key, (ualg->alg_key_len + 7) / 8); |
308 | 308 | ||
309 | *algpp = p; | 309 | *algpp = p; |
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int attach_auth_trunc(struct xfrm_algo_auth **algpp, u8 *props, | 313 | static int attach_auth_trunc(struct xfrm_algo_auth **algpp, u8 *props, |
314 | struct nlattr *rta) | 314 | struct nlattr *rta) |
315 | { | 315 | { |
316 | struct xfrm_algo_auth *p, *ualg; | 316 | struct xfrm_algo_auth *p, *ualg; |
317 | struct xfrm_algo_desc *algo; | 317 | struct xfrm_algo_desc *algo; |
318 | 318 | ||
319 | if (!rta) | 319 | if (!rta) |
320 | return 0; | 320 | return 0; |
321 | 321 | ||
322 | ualg = nla_data(rta); | 322 | ualg = nla_data(rta); |
323 | 323 | ||
324 | algo = xfrm_aalg_get_byname(ualg->alg_name, 1); | 324 | algo = xfrm_aalg_get_byname(ualg->alg_name, 1); |
325 | if (!algo) | 325 | if (!algo) |
326 | return -ENOSYS; | 326 | return -ENOSYS; |
327 | if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN || | 327 | if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN || |
328 | ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits) | 328 | ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits) |
329 | return -EINVAL; | 329 | return -EINVAL; |
330 | *props = algo->desc.sadb_alg_id; | 330 | *props = algo->desc.sadb_alg_id; |
331 | 331 | ||
332 | p = kmemdup(ualg, xfrm_alg_auth_len(ualg), GFP_KERNEL); | 332 | p = kmemdup(ualg, xfrm_alg_auth_len(ualg), GFP_KERNEL); |
333 | if (!p) | 333 | if (!p) |
334 | return -ENOMEM; | 334 | return -ENOMEM; |
335 | 335 | ||
336 | strcpy(p->alg_name, algo->name); | 336 | strcpy(p->alg_name, algo->name); |
337 | if (!p->alg_trunc_len) | 337 | if (!p->alg_trunc_len) |
338 | p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; | 338 | p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; |
339 | 339 | ||
340 | *algpp = p; | 340 | *algpp = p; |
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | 344 | static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, |
345 | struct nlattr *rta) | 345 | struct nlattr *rta) |
346 | { | 346 | { |
347 | struct xfrm_algo_aead *p, *ualg; | 347 | struct xfrm_algo_aead *p, *ualg; |
348 | struct xfrm_algo_desc *algo; | 348 | struct xfrm_algo_desc *algo; |
349 | 349 | ||
350 | if (!rta) | 350 | if (!rta) |
351 | return 0; | 351 | return 0; |
352 | 352 | ||
353 | ualg = nla_data(rta); | 353 | ualg = nla_data(rta); |
354 | 354 | ||
355 | algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1); | 355 | algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1); |
356 | if (!algo) | 356 | if (!algo) |
357 | return -ENOSYS; | 357 | return -ENOSYS; |
358 | *props = algo->desc.sadb_alg_id; | 358 | *props = algo->desc.sadb_alg_id; |
359 | 359 | ||
360 | p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL); | 360 | p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL); |
361 | if (!p) | 361 | if (!p) |
362 | return -ENOMEM; | 362 | return -ENOMEM; |
363 | 363 | ||
364 | strcpy(p->alg_name, algo->name); | 364 | strcpy(p->alg_name, algo->name); |
365 | *algpp = p; | 365 | *algpp = p; |
366 | return 0; | 366 | return 0; |
367 | } | 367 | } |
368 | 368 | ||
369 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | 369 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, |
370 | struct nlattr *rp) | 370 | struct nlattr *rp) |
371 | { | 371 | { |
372 | struct xfrm_replay_state_esn *up; | 372 | struct xfrm_replay_state_esn *up; |
373 | 373 | ||
374 | if (!replay_esn || !rp) | 374 | if (!replay_esn || !rp) |
375 | return 0; | 375 | return 0; |
376 | 376 | ||
377 | up = nla_data(rp); | 377 | up = nla_data(rp); |
378 | 378 | ||
379 | if (xfrm_replay_state_esn_len(replay_esn) != | 379 | if (xfrm_replay_state_esn_len(replay_esn) != |
380 | xfrm_replay_state_esn_len(up)) | 380 | xfrm_replay_state_esn_len(up)) |
381 | return -EINVAL; | 381 | return -EINVAL; |
382 | 382 | ||
383 | return 0; | 383 | return 0; |
384 | } | 384 | } |
385 | 385 | ||
386 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 386 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
387 | struct xfrm_replay_state_esn **preplay_esn, | 387 | struct xfrm_replay_state_esn **preplay_esn, |
388 | struct nlattr *rta) | 388 | struct nlattr *rta) |
389 | { | 389 | { |
390 | struct xfrm_replay_state_esn *p, *pp, *up; | 390 | struct xfrm_replay_state_esn *p, *pp, *up; |
391 | 391 | ||
392 | if (!rta) | 392 | if (!rta) |
393 | return 0; | 393 | return 0; |
394 | 394 | ||
395 | up = nla_data(rta); | 395 | up = nla_data(rta); |
396 | 396 | ||
397 | p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); | 397 | p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); |
398 | if (!p) | 398 | if (!p) |
399 | return -ENOMEM; | 399 | return -ENOMEM; |
400 | 400 | ||
401 | pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); | 401 | pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); |
402 | if (!pp) { | 402 | if (!pp) { |
403 | kfree(p); | 403 | kfree(p); |
404 | return -ENOMEM; | 404 | return -ENOMEM; |
405 | } | 405 | } |
406 | 406 | ||
407 | *replay_esn = p; | 407 | *replay_esn = p; |
408 | *preplay_esn = pp; | 408 | *preplay_esn = pp; |
409 | 409 | ||
410 | return 0; | 410 | return 0; |
411 | } | 411 | } |
412 | 412 | ||
413 | static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) | 413 | static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) |
414 | { | 414 | { |
415 | int len = 0; | 415 | int len = 0; |
416 | 416 | ||
417 | if (xfrm_ctx) { | 417 | if (xfrm_ctx) { |
418 | len += sizeof(struct xfrm_user_sec_ctx); | 418 | len += sizeof(struct xfrm_user_sec_ctx); |
419 | len += xfrm_ctx->ctx_len; | 419 | len += xfrm_ctx->ctx_len; |
420 | } | 420 | } |
421 | return len; | 421 | return len; |
422 | } | 422 | } |
423 | 423 | ||
424 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) | 424 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) |
425 | { | 425 | { |
426 | memcpy(&x->id, &p->id, sizeof(x->id)); | 426 | memcpy(&x->id, &p->id, sizeof(x->id)); |
427 | memcpy(&x->sel, &p->sel, sizeof(x->sel)); | 427 | memcpy(&x->sel, &p->sel, sizeof(x->sel)); |
428 | memcpy(&x->lft, &p->lft, sizeof(x->lft)); | 428 | memcpy(&x->lft, &p->lft, sizeof(x->lft)); |
429 | x->props.mode = p->mode; | 429 | x->props.mode = p->mode; |
430 | x->props.replay_window = p->replay_window; | 430 | x->props.replay_window = p->replay_window; |
431 | x->props.reqid = p->reqid; | 431 | x->props.reqid = p->reqid; |
432 | x->props.family = p->family; | 432 | x->props.family = p->family; |
433 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); | 433 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); |
434 | x->props.flags = p->flags; | 434 | x->props.flags = p->flags; |
435 | 435 | ||
436 | if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC)) | 436 | if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC)) |
437 | x->sel.family = p->family; | 437 | x->sel.family = p->family; |
438 | } | 438 | } |
439 | 439 | ||
440 | /* | 440 | /* |
441 | * someday when pfkey also has support, we could have the code | 441 | * someday when pfkey also has support, we could have the code |
442 | * somehow made shareable and move it to xfrm_state.c - JHS | 442 | * somehow made shareable and move it to xfrm_state.c - JHS |
443 | * | 443 | * |
444 | */ | 444 | */ |
445 | static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) | 445 | static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) |
446 | { | 446 | { |
447 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 447 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
448 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; | 448 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; |
449 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 449 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
450 | struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; | 450 | struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; |
451 | struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; | 451 | struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; |
452 | 452 | ||
453 | if (re) { | 453 | if (re) { |
454 | struct xfrm_replay_state_esn *replay_esn; | 454 | struct xfrm_replay_state_esn *replay_esn; |
455 | replay_esn = nla_data(re); | 455 | replay_esn = nla_data(re); |
456 | memcpy(x->replay_esn, replay_esn, | 456 | memcpy(x->replay_esn, replay_esn, |
457 | xfrm_replay_state_esn_len(replay_esn)); | 457 | xfrm_replay_state_esn_len(replay_esn)); |
458 | memcpy(x->preplay_esn, replay_esn, | 458 | memcpy(x->preplay_esn, replay_esn, |
459 | xfrm_replay_state_esn_len(replay_esn)); | 459 | xfrm_replay_state_esn_len(replay_esn)); |
460 | } | 460 | } |
461 | 461 | ||
462 | if (rp) { | 462 | if (rp) { |
463 | struct xfrm_replay_state *replay; | 463 | struct xfrm_replay_state *replay; |
464 | replay = nla_data(rp); | 464 | replay = nla_data(rp); |
465 | memcpy(&x->replay, replay, sizeof(*replay)); | 465 | memcpy(&x->replay, replay, sizeof(*replay)); |
466 | memcpy(&x->preplay, replay, sizeof(*replay)); | 466 | memcpy(&x->preplay, replay, sizeof(*replay)); |
467 | } | 467 | } |
468 | 468 | ||
469 | if (lt) { | 469 | if (lt) { |
470 | struct xfrm_lifetime_cur *ltime; | 470 | struct xfrm_lifetime_cur *ltime; |
471 | ltime = nla_data(lt); | 471 | ltime = nla_data(lt); |
472 | x->curlft.bytes = ltime->bytes; | 472 | x->curlft.bytes = ltime->bytes; |
473 | x->curlft.packets = ltime->packets; | 473 | x->curlft.packets = ltime->packets; |
474 | x->curlft.add_time = ltime->add_time; | 474 | x->curlft.add_time = ltime->add_time; |
475 | x->curlft.use_time = ltime->use_time; | 475 | x->curlft.use_time = ltime->use_time; |
476 | } | 476 | } |
477 | 477 | ||
478 | if (et) | 478 | if (et) |
479 | x->replay_maxage = nla_get_u32(et); | 479 | x->replay_maxage = nla_get_u32(et); |
480 | 480 | ||
481 | if (rt) | 481 | if (rt) |
482 | x->replay_maxdiff = nla_get_u32(rt); | 482 | x->replay_maxdiff = nla_get_u32(rt); |
483 | } | 483 | } |
484 | 484 | ||
485 | static struct xfrm_state *xfrm_state_construct(struct net *net, | 485 | static struct xfrm_state *xfrm_state_construct(struct net *net, |
486 | struct xfrm_usersa_info *p, | 486 | struct xfrm_usersa_info *p, |
487 | struct nlattr **attrs, | 487 | struct nlattr **attrs, |
488 | int *errp) | 488 | int *errp) |
489 | { | 489 | { |
490 | struct xfrm_state *x = xfrm_state_alloc(net); | 490 | struct xfrm_state *x = xfrm_state_alloc(net); |
491 | int err = -ENOMEM; | 491 | int err = -ENOMEM; |
492 | 492 | ||
493 | if (!x) | 493 | if (!x) |
494 | goto error_no_put; | 494 | goto error_no_put; |
495 | 495 | ||
496 | copy_from_user_state(x, p); | 496 | copy_from_user_state(x, p); |
497 | 497 | ||
498 | if ((err = attach_aead(&x->aead, &x->props.ealgo, | 498 | if ((err = attach_aead(&x->aead, &x->props.ealgo, |
499 | attrs[XFRMA_ALG_AEAD]))) | 499 | attrs[XFRMA_ALG_AEAD]))) |
500 | goto error; | 500 | goto error; |
501 | if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo, | 501 | if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo, |
502 | attrs[XFRMA_ALG_AUTH_TRUNC]))) | 502 | attrs[XFRMA_ALG_AUTH_TRUNC]))) |
503 | goto error; | 503 | goto error; |
504 | if (!x->props.aalgo) { | 504 | if (!x->props.aalgo) { |
505 | if ((err = attach_auth(&x->aalg, &x->props.aalgo, | 505 | if ((err = attach_auth(&x->aalg, &x->props.aalgo, |
506 | attrs[XFRMA_ALG_AUTH]))) | 506 | attrs[XFRMA_ALG_AUTH]))) |
507 | goto error; | 507 | goto error; |
508 | } | 508 | } |
509 | if ((err = attach_one_algo(&x->ealg, &x->props.ealgo, | 509 | if ((err = attach_one_algo(&x->ealg, &x->props.ealgo, |
510 | xfrm_ealg_get_byname, | 510 | xfrm_ealg_get_byname, |
511 | attrs[XFRMA_ALG_CRYPT]))) | 511 | attrs[XFRMA_ALG_CRYPT]))) |
512 | goto error; | 512 | goto error; |
513 | if ((err = attach_one_algo(&x->calg, &x->props.calgo, | 513 | if ((err = attach_one_algo(&x->calg, &x->props.calgo, |
514 | xfrm_calg_get_byname, | 514 | xfrm_calg_get_byname, |
515 | attrs[XFRMA_ALG_COMP]))) | 515 | attrs[XFRMA_ALG_COMP]))) |
516 | goto error; | 516 | goto error; |
517 | 517 | ||
518 | if (attrs[XFRMA_ENCAP]) { | 518 | if (attrs[XFRMA_ENCAP]) { |
519 | x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), | 519 | x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), |
520 | sizeof(*x->encap), GFP_KERNEL); | 520 | sizeof(*x->encap), GFP_KERNEL); |
521 | if (x->encap == NULL) | 521 | if (x->encap == NULL) |
522 | goto error; | 522 | goto error; |
523 | } | 523 | } |
524 | 524 | ||
525 | if (attrs[XFRMA_TFCPAD]) | 525 | if (attrs[XFRMA_TFCPAD]) |
526 | x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]); | 526 | x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]); |
527 | 527 | ||
528 | if (attrs[XFRMA_COADDR]) { | 528 | if (attrs[XFRMA_COADDR]) { |
529 | x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), | 529 | x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), |
530 | sizeof(*x->coaddr), GFP_KERNEL); | 530 | sizeof(*x->coaddr), GFP_KERNEL); |
531 | if (x->coaddr == NULL) | 531 | if (x->coaddr == NULL) |
532 | goto error; | 532 | goto error; |
533 | } | 533 | } |
534 | 534 | ||
535 | xfrm_mark_get(attrs, &x->mark); | 535 | xfrm_mark_get(attrs, &x->mark); |
536 | 536 | ||
537 | err = __xfrm_init_state(x, false); | 537 | err = __xfrm_init_state(x, false); |
538 | if (err) | 538 | if (err) |
539 | goto error; | 539 | goto error; |
540 | 540 | ||
541 | if (attrs[XFRMA_SEC_CTX] && | 541 | if (attrs[XFRMA_SEC_CTX] && |
542 | security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) | 542 | security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) |
543 | goto error; | 543 | goto error; |
544 | 544 | ||
545 | if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, | 545 | if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, |
546 | attrs[XFRMA_REPLAY_ESN_VAL]))) | 546 | attrs[XFRMA_REPLAY_ESN_VAL]))) |
547 | goto error; | 547 | goto error; |
548 | 548 | ||
549 | x->km.seq = p->seq; | 549 | x->km.seq = p->seq; |
550 | x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; | 550 | x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; |
551 | /* sysctl_xfrm_aevent_etime is in 100ms units */ | 551 | /* sysctl_xfrm_aevent_etime is in 100ms units */ |
552 | x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; | 552 | x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; |
553 | 553 | ||
554 | if ((err = xfrm_init_replay(x))) | 554 | if ((err = xfrm_init_replay(x))) |
555 | goto error; | 555 | goto error; |
556 | 556 | ||
557 | /* override default values from above */ | 557 | /* override default values from above */ |
558 | xfrm_update_ae_params(x, attrs); | 558 | xfrm_update_ae_params(x, attrs); |
559 | 559 | ||
560 | return x; | 560 | return x; |
561 | 561 | ||
562 | error: | 562 | error: |
563 | x->km.state = XFRM_STATE_DEAD; | 563 | x->km.state = XFRM_STATE_DEAD; |
564 | xfrm_state_put(x); | 564 | xfrm_state_put(x); |
565 | error_no_put: | 565 | error_no_put: |
566 | *errp = err; | 566 | *errp = err; |
567 | return NULL; | 567 | return NULL; |
568 | } | 568 | } |
569 | 569 | ||
570 | static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 570 | static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
571 | struct nlattr **attrs) | 571 | struct nlattr **attrs) |
572 | { | 572 | { |
573 | struct net *net = sock_net(skb->sk); | 573 | struct net *net = sock_net(skb->sk); |
574 | struct xfrm_usersa_info *p = nlmsg_data(nlh); | 574 | struct xfrm_usersa_info *p = nlmsg_data(nlh); |
575 | struct xfrm_state *x; | 575 | struct xfrm_state *x; |
576 | int err; | 576 | int err; |
577 | struct km_event c; | 577 | struct km_event c; |
578 | uid_t loginuid = audit_get_loginuid(current); | 578 | uid_t loginuid = audit_get_loginuid(current); |
579 | u32 sessionid = audit_get_sessionid(current); | 579 | u32 sessionid = audit_get_sessionid(current); |
580 | u32 sid; | 580 | u32 sid; |
581 | 581 | ||
582 | err = verify_newsa_info(p, attrs); | 582 | err = verify_newsa_info(p, attrs); |
583 | if (err) | 583 | if (err) |
584 | return err; | 584 | return err; |
585 | 585 | ||
586 | x = xfrm_state_construct(net, p, attrs, &err); | 586 | x = xfrm_state_construct(net, p, attrs, &err); |
587 | if (!x) | 587 | if (!x) |
588 | return err; | 588 | return err; |
589 | 589 | ||
590 | xfrm_state_hold(x); | 590 | xfrm_state_hold(x); |
591 | if (nlh->nlmsg_type == XFRM_MSG_NEWSA) | 591 | if (nlh->nlmsg_type == XFRM_MSG_NEWSA) |
592 | err = xfrm_state_add(x); | 592 | err = xfrm_state_add(x); |
593 | else | 593 | else |
594 | err = xfrm_state_update(x); | 594 | err = xfrm_state_update(x); |
595 | 595 | ||
596 | security_task_getsecid(current, &sid); | 596 | security_task_getsecid(current, &sid); |
597 | xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid); | 597 | xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid); |
598 | 598 | ||
599 | if (err < 0) { | 599 | if (err < 0) { |
600 | x->km.state = XFRM_STATE_DEAD; | 600 | x->km.state = XFRM_STATE_DEAD; |
601 | __xfrm_state_put(x); | 601 | __xfrm_state_put(x); |
602 | goto out; | 602 | goto out; |
603 | } | 603 | } |
604 | 604 | ||
605 | c.seq = nlh->nlmsg_seq; | 605 | c.seq = nlh->nlmsg_seq; |
606 | c.pid = nlh->nlmsg_pid; | 606 | c.pid = nlh->nlmsg_pid; |
607 | c.event = nlh->nlmsg_type; | 607 | c.event = nlh->nlmsg_type; |
608 | 608 | ||
609 | km_state_notify(x, &c); | 609 | km_state_notify(x, &c); |
610 | out: | 610 | out: |
611 | xfrm_state_put(x); | 611 | xfrm_state_put(x); |
612 | return err; | 612 | return err; |
613 | } | 613 | } |
614 | 614 | ||
615 | static struct xfrm_state *xfrm_user_state_lookup(struct net *net, | 615 | static struct xfrm_state *xfrm_user_state_lookup(struct net *net, |
616 | struct xfrm_usersa_id *p, | 616 | struct xfrm_usersa_id *p, |
617 | struct nlattr **attrs, | 617 | struct nlattr **attrs, |
618 | int *errp) | 618 | int *errp) |
619 | { | 619 | { |
620 | struct xfrm_state *x = NULL; | 620 | struct xfrm_state *x = NULL; |
621 | struct xfrm_mark m; | 621 | struct xfrm_mark m; |
622 | int err; | 622 | int err; |
623 | u32 mark = xfrm_mark_get(attrs, &m); | 623 | u32 mark = xfrm_mark_get(attrs, &m); |
624 | 624 | ||
625 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { | 625 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { |
626 | err = -ESRCH; | 626 | err = -ESRCH; |
627 | x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); | 627 | x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); |
628 | } else { | 628 | } else { |
629 | xfrm_address_t *saddr = NULL; | 629 | xfrm_address_t *saddr = NULL; |
630 | 630 | ||
631 | verify_one_addr(attrs, XFRMA_SRCADDR, &saddr); | 631 | verify_one_addr(attrs, XFRMA_SRCADDR, &saddr); |
632 | if (!saddr) { | 632 | if (!saddr) { |
633 | err = -EINVAL; | 633 | err = -EINVAL; |
634 | goto out; | 634 | goto out; |
635 | } | 635 | } |
636 | 636 | ||
637 | err = -ESRCH; | 637 | err = -ESRCH; |
638 | x = xfrm_state_lookup_byaddr(net, mark, | 638 | x = xfrm_state_lookup_byaddr(net, mark, |
639 | &p->daddr, saddr, | 639 | &p->daddr, saddr, |
640 | p->proto, p->family); | 640 | p->proto, p->family); |
641 | } | 641 | } |
642 | 642 | ||
643 | out: | 643 | out: |
644 | if (!x && errp) | 644 | if (!x && errp) |
645 | *errp = err; | 645 | *errp = err; |
646 | return x; | 646 | return x; |
647 | } | 647 | } |
648 | 648 | ||
649 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 649 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
650 | struct nlattr **attrs) | 650 | struct nlattr **attrs) |
651 | { | 651 | { |
652 | struct net *net = sock_net(skb->sk); | 652 | struct net *net = sock_net(skb->sk); |
653 | struct xfrm_state *x; | 653 | struct xfrm_state *x; |
654 | int err = -ESRCH; | 654 | int err = -ESRCH; |
655 | struct km_event c; | 655 | struct km_event c; |
656 | struct xfrm_usersa_id *p = nlmsg_data(nlh); | 656 | struct xfrm_usersa_id *p = nlmsg_data(nlh); |
657 | uid_t loginuid = audit_get_loginuid(current); | 657 | uid_t loginuid = audit_get_loginuid(current); |
658 | u32 sessionid = audit_get_sessionid(current); | 658 | u32 sessionid = audit_get_sessionid(current); |
659 | u32 sid; | 659 | u32 sid; |
660 | 660 | ||
661 | x = xfrm_user_state_lookup(net, p, attrs, &err); | 661 | x = xfrm_user_state_lookup(net, p, attrs, &err); |
662 | if (x == NULL) | 662 | if (x == NULL) |
663 | return err; | 663 | return err; |
664 | 664 | ||
665 | if ((err = security_xfrm_state_delete(x)) != 0) | 665 | if ((err = security_xfrm_state_delete(x)) != 0) |
666 | goto out; | 666 | goto out; |
667 | 667 | ||
668 | if (xfrm_state_kern(x)) { | 668 | if (xfrm_state_kern(x)) { |
669 | err = -EPERM; | 669 | err = -EPERM; |
670 | goto out; | 670 | goto out; |
671 | } | 671 | } |
672 | 672 | ||
673 | err = xfrm_state_delete(x); | 673 | err = xfrm_state_delete(x); |
674 | 674 | ||
675 | if (err < 0) | 675 | if (err < 0) |
676 | goto out; | 676 | goto out; |
677 | 677 | ||
678 | c.seq = nlh->nlmsg_seq; | 678 | c.seq = nlh->nlmsg_seq; |
679 | c.pid = nlh->nlmsg_pid; | 679 | c.pid = nlh->nlmsg_pid; |
680 | c.event = nlh->nlmsg_type; | 680 | c.event = nlh->nlmsg_type; |
681 | km_state_notify(x, &c); | 681 | km_state_notify(x, &c); |
682 | 682 | ||
683 | out: | 683 | out: |
684 | security_task_getsecid(current, &sid); | 684 | security_task_getsecid(current, &sid); |
685 | xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid); | 685 | xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid); |
686 | xfrm_state_put(x); | 686 | xfrm_state_put(x); |
687 | return err; | 687 | return err; |
688 | } | 688 | } |
689 | 689 | ||
690 | static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) | 690 | static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) |
691 | { | 691 | { |
692 | memcpy(&p->id, &x->id, sizeof(p->id)); | 692 | memcpy(&p->id, &x->id, sizeof(p->id)); |
693 | memcpy(&p->sel, &x->sel, sizeof(p->sel)); | 693 | memcpy(&p->sel, &x->sel, sizeof(p->sel)); |
694 | memcpy(&p->lft, &x->lft, sizeof(p->lft)); | 694 | memcpy(&p->lft, &x->lft, sizeof(p->lft)); |
695 | memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); | 695 | memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); |
696 | memcpy(&p->stats, &x->stats, sizeof(p->stats)); | 696 | memcpy(&p->stats, &x->stats, sizeof(p->stats)); |
697 | memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr)); | 697 | memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr)); |
698 | p->mode = x->props.mode; | 698 | p->mode = x->props.mode; |
699 | p->replay_window = x->props.replay_window; | 699 | p->replay_window = x->props.replay_window; |
700 | p->reqid = x->props.reqid; | 700 | p->reqid = x->props.reqid; |
701 | p->family = x->props.family; | 701 | p->family = x->props.family; |
702 | p->flags = x->props.flags; | 702 | p->flags = x->props.flags; |
703 | p->seq = x->km.seq; | 703 | p->seq = x->km.seq; |
704 | } | 704 | } |
705 | 705 | ||
706 | struct xfrm_dump_info { | 706 | struct xfrm_dump_info { |
707 | struct sk_buff *in_skb; | 707 | struct sk_buff *in_skb; |
708 | struct sk_buff *out_skb; | 708 | struct sk_buff *out_skb; |
709 | u32 nlmsg_seq; | 709 | u32 nlmsg_seq; |
710 | u16 nlmsg_flags; | 710 | u16 nlmsg_flags; |
711 | }; | 711 | }; |
712 | 712 | ||
713 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) | 713 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) |
714 | { | 714 | { |
715 | struct xfrm_user_sec_ctx *uctx; | 715 | struct xfrm_user_sec_ctx *uctx; |
716 | struct nlattr *attr; | 716 | struct nlattr *attr; |
717 | int ctx_size = sizeof(*uctx) + s->ctx_len; | 717 | int ctx_size = sizeof(*uctx) + s->ctx_len; |
718 | 718 | ||
719 | attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size); | 719 | attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size); |
720 | if (attr == NULL) | 720 | if (attr == NULL) |
721 | return -EMSGSIZE; | 721 | return -EMSGSIZE; |
722 | 722 | ||
723 | uctx = nla_data(attr); | 723 | uctx = nla_data(attr); |
724 | uctx->exttype = XFRMA_SEC_CTX; | 724 | uctx->exttype = XFRMA_SEC_CTX; |
725 | uctx->len = ctx_size; | 725 | uctx->len = ctx_size; |
726 | uctx->ctx_doi = s->ctx_doi; | 726 | uctx->ctx_doi = s->ctx_doi; |
727 | uctx->ctx_alg = s->ctx_alg; | 727 | uctx->ctx_alg = s->ctx_alg; |
728 | uctx->ctx_len = s->ctx_len; | 728 | uctx->ctx_len = s->ctx_len; |
729 | memcpy(uctx + 1, s->ctx_str, s->ctx_len); | 729 | memcpy(uctx + 1, s->ctx_str, s->ctx_len); |
730 | 730 | ||
731 | return 0; | 731 | return 0; |
732 | } | 732 | } |
733 | 733 | ||
734 | static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) | 734 | static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) |
735 | { | 735 | { |
736 | struct xfrm_algo *algo; | 736 | struct xfrm_algo *algo; |
737 | struct nlattr *nla; | 737 | struct nlattr *nla; |
738 | 738 | ||
739 | nla = nla_reserve(skb, XFRMA_ALG_AUTH, | 739 | nla = nla_reserve(skb, XFRMA_ALG_AUTH, |
740 | sizeof(*algo) + (auth->alg_key_len + 7) / 8); | 740 | sizeof(*algo) + (auth->alg_key_len + 7) / 8); |
741 | if (!nla) | 741 | if (!nla) |
742 | return -EMSGSIZE; | 742 | return -EMSGSIZE; |
743 | 743 | ||
744 | algo = nla_data(nla); | 744 | algo = nla_data(nla); |
745 | strcpy(algo->alg_name, auth->alg_name); | 745 | strcpy(algo->alg_name, auth->alg_name); |
746 | memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); | 746 | memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); |
747 | algo->alg_key_len = auth->alg_key_len; | 747 | algo->alg_key_len = auth->alg_key_len; |
748 | 748 | ||
749 | return 0; | 749 | return 0; |
750 | } | 750 | } |
751 | 751 | ||
752 | /* Don't change this without updating xfrm_sa_len! */ | 752 | /* Don't change this without updating xfrm_sa_len! */ |
753 | static int copy_to_user_state_extra(struct xfrm_state *x, | 753 | static int copy_to_user_state_extra(struct xfrm_state *x, |
754 | struct xfrm_usersa_info *p, | 754 | struct xfrm_usersa_info *p, |
755 | struct sk_buff *skb) | 755 | struct sk_buff *skb) |
756 | { | 756 | { |
757 | copy_to_user_state(x, p); | 757 | copy_to_user_state(x, p); |
758 | 758 | ||
759 | if (x->coaddr) | 759 | if (x->coaddr) |
760 | NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); | 760 | NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); |
761 | 761 | ||
762 | if (x->lastused) | 762 | if (x->lastused) |
763 | NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); | 763 | NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); |
764 | 764 | ||
765 | if (x->aead) | 765 | if (x->aead) |
766 | NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead); | 766 | NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead); |
767 | if (x->aalg) { | 767 | if (x->aalg) { |
768 | if (copy_to_user_auth(x->aalg, skb)) | 768 | if (copy_to_user_auth(x->aalg, skb)) |
769 | goto nla_put_failure; | 769 | goto nla_put_failure; |
770 | 770 | ||
771 | NLA_PUT(skb, XFRMA_ALG_AUTH_TRUNC, | 771 | NLA_PUT(skb, XFRMA_ALG_AUTH_TRUNC, |
772 | xfrm_alg_auth_len(x->aalg), x->aalg); | 772 | xfrm_alg_auth_len(x->aalg), x->aalg); |
773 | } | 773 | } |
774 | if (x->ealg) | 774 | if (x->ealg) |
775 | NLA_PUT(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg); | 775 | NLA_PUT(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg); |
776 | if (x->calg) | 776 | if (x->calg) |
777 | NLA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); | 777 | NLA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); |
778 | 778 | ||
779 | if (x->encap) | 779 | if (x->encap) |
780 | NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); | 780 | NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); |
781 | 781 | ||
782 | if (x->tfcpad) | 782 | if (x->tfcpad) |
783 | NLA_PUT_U32(skb, XFRMA_TFCPAD, x->tfcpad); | 783 | NLA_PUT_U32(skb, XFRMA_TFCPAD, x->tfcpad); |
784 | 784 | ||
785 | if (xfrm_mark_put(skb, &x->mark)) | 785 | if (xfrm_mark_put(skb, &x->mark)) |
786 | goto nla_put_failure; | 786 | goto nla_put_failure; |
787 | 787 | ||
788 | if (x->replay_esn) | 788 | if (x->replay_esn) |
789 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, | 789 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, |
790 | xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); | 790 | xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); |
791 | 791 | ||
792 | if (x->security && copy_sec_ctx(x->security, skb) < 0) | 792 | if (x->security && copy_sec_ctx(x->security, skb) < 0) |
793 | goto nla_put_failure; | 793 | goto nla_put_failure; |
794 | 794 | ||
795 | return 0; | 795 | return 0; |
796 | 796 | ||
797 | nla_put_failure: | 797 | nla_put_failure: |
798 | return -EMSGSIZE; | 798 | return -EMSGSIZE; |
799 | } | 799 | } |
800 | 800 | ||
801 | static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | 801 | static int dump_one_state(struct xfrm_state *x, int count, void *ptr) |
802 | { | 802 | { |
803 | struct xfrm_dump_info *sp = ptr; | 803 | struct xfrm_dump_info *sp = ptr; |
804 | struct sk_buff *in_skb = sp->in_skb; | 804 | struct sk_buff *in_skb = sp->in_skb; |
805 | struct sk_buff *skb = sp->out_skb; | 805 | struct sk_buff *skb = sp->out_skb; |
806 | struct xfrm_usersa_info *p; | 806 | struct xfrm_usersa_info *p; |
807 | struct nlmsghdr *nlh; | 807 | struct nlmsghdr *nlh; |
808 | int err; | 808 | int err; |
809 | 809 | ||
810 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | 810 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, |
811 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); | 811 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); |
812 | if (nlh == NULL) | 812 | if (nlh == NULL) |
813 | return -EMSGSIZE; | 813 | return -EMSGSIZE; |
814 | 814 | ||
815 | p = nlmsg_data(nlh); | 815 | p = nlmsg_data(nlh); |
816 | 816 | ||
817 | err = copy_to_user_state_extra(x, p, skb); | 817 | err = copy_to_user_state_extra(x, p, skb); |
818 | if (err) | 818 | if (err) |
819 | goto nla_put_failure; | 819 | goto nla_put_failure; |
820 | 820 | ||
821 | nlmsg_end(skb, nlh); | 821 | nlmsg_end(skb, nlh); |
822 | return 0; | 822 | return 0; |
823 | 823 | ||
824 | nla_put_failure: | 824 | nla_put_failure: |
825 | nlmsg_cancel(skb, nlh); | 825 | nlmsg_cancel(skb, nlh); |
826 | return err; | 826 | return err; |
827 | } | 827 | } |
828 | 828 | ||
829 | static int xfrm_dump_sa_done(struct netlink_callback *cb) | 829 | static int xfrm_dump_sa_done(struct netlink_callback *cb) |
830 | { | 830 | { |
831 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; | 831 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; |
832 | xfrm_state_walk_done(walk); | 832 | xfrm_state_walk_done(walk); |
833 | return 0; | 833 | return 0; |
834 | } | 834 | } |
835 | 835 | ||
836 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 836 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
837 | { | 837 | { |
838 | struct net *net = sock_net(skb->sk); | 838 | struct net *net = sock_net(skb->sk); |
839 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; | 839 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; |
840 | struct xfrm_dump_info info; | 840 | struct xfrm_dump_info info; |
841 | 841 | ||
842 | BUILD_BUG_ON(sizeof(struct xfrm_state_walk) > | 842 | BUILD_BUG_ON(sizeof(struct xfrm_state_walk) > |
843 | sizeof(cb->args) - sizeof(cb->args[0])); | 843 | sizeof(cb->args) - sizeof(cb->args[0])); |
844 | 844 | ||
845 | info.in_skb = cb->skb; | 845 | info.in_skb = cb->skb; |
846 | info.out_skb = skb; | 846 | info.out_skb = skb; |
847 | info.nlmsg_seq = cb->nlh->nlmsg_seq; | 847 | info.nlmsg_seq = cb->nlh->nlmsg_seq; |
848 | info.nlmsg_flags = NLM_F_MULTI; | 848 | info.nlmsg_flags = NLM_F_MULTI; |
849 | 849 | ||
850 | if (!cb->args[0]) { | 850 | if (!cb->args[0]) { |
851 | cb->args[0] = 1; | 851 | cb->args[0] = 1; |
852 | xfrm_state_walk_init(walk, 0); | 852 | xfrm_state_walk_init(walk, 0); |
853 | } | 853 | } |
854 | 854 | ||
855 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); | 855 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); |
856 | 856 | ||
857 | return skb->len; | 857 | return skb->len; |
858 | } | 858 | } |
859 | 859 | ||
860 | static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, | 860 | static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, |
861 | struct xfrm_state *x, u32 seq) | 861 | struct xfrm_state *x, u32 seq) |
862 | { | 862 | { |
863 | struct xfrm_dump_info info; | 863 | struct xfrm_dump_info info; |
864 | struct sk_buff *skb; | 864 | struct sk_buff *skb; |
865 | 865 | ||
866 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 866 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
867 | if (!skb) | 867 | if (!skb) |
868 | return ERR_PTR(-ENOMEM); | 868 | return ERR_PTR(-ENOMEM); |
869 | 869 | ||
870 | info.in_skb = in_skb; | 870 | info.in_skb = in_skb; |
871 | info.out_skb = skb; | 871 | info.out_skb = skb; |
872 | info.nlmsg_seq = seq; | 872 | info.nlmsg_seq = seq; |
873 | info.nlmsg_flags = 0; | 873 | info.nlmsg_flags = 0; |
874 | 874 | ||
875 | if (dump_one_state(x, 0, &info)) { | 875 | if (dump_one_state(x, 0, &info)) { |
876 | kfree_skb(skb); | 876 | kfree_skb(skb); |
877 | return NULL; | 877 | return NULL; |
878 | } | 878 | } |
879 | 879 | ||
880 | return skb; | 880 | return skb; |
881 | } | 881 | } |
882 | 882 | ||
883 | static inline size_t xfrm_spdinfo_msgsize(void) | 883 | static inline size_t xfrm_spdinfo_msgsize(void) |
884 | { | 884 | { |
885 | return NLMSG_ALIGN(4) | 885 | return NLMSG_ALIGN(4) |
886 | + nla_total_size(sizeof(struct xfrmu_spdinfo)) | 886 | + nla_total_size(sizeof(struct xfrmu_spdinfo)) |
887 | + nla_total_size(sizeof(struct xfrmu_spdhinfo)); | 887 | + nla_total_size(sizeof(struct xfrmu_spdhinfo)); |
888 | } | 888 | } |
889 | 889 | ||
890 | static int build_spdinfo(struct sk_buff *skb, struct net *net, | 890 | static int build_spdinfo(struct sk_buff *skb, struct net *net, |
891 | u32 pid, u32 seq, u32 flags) | 891 | u32 pid, u32 seq, u32 flags) |
892 | { | 892 | { |
893 | struct xfrmk_spdinfo si; | 893 | struct xfrmk_spdinfo si; |
894 | struct xfrmu_spdinfo spc; | 894 | struct xfrmu_spdinfo spc; |
895 | struct xfrmu_spdhinfo sph; | 895 | struct xfrmu_spdhinfo sph; |
896 | struct nlmsghdr *nlh; | 896 | struct nlmsghdr *nlh; |
897 | u32 *f; | 897 | u32 *f; |
898 | 898 | ||
899 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 899 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
900 | if (nlh == NULL) /* shouldn't really happen ... */ | 900 | if (nlh == NULL) /* shouldn't really happen ... */ |
901 | return -EMSGSIZE; | 901 | return -EMSGSIZE; |
902 | 902 | ||
903 | f = nlmsg_data(nlh); | 903 | f = nlmsg_data(nlh); |
904 | *f = flags; | 904 | *f = flags; |
905 | xfrm_spd_getinfo(net, &si); | 905 | xfrm_spd_getinfo(net, &si); |
906 | spc.incnt = si.incnt; | 906 | spc.incnt = si.incnt; |
907 | spc.outcnt = si.outcnt; | 907 | spc.outcnt = si.outcnt; |
908 | spc.fwdcnt = si.fwdcnt; | 908 | spc.fwdcnt = si.fwdcnt; |
909 | spc.inscnt = si.inscnt; | 909 | spc.inscnt = si.inscnt; |
910 | spc.outscnt = si.outscnt; | 910 | spc.outscnt = si.outscnt; |
911 | spc.fwdscnt = si.fwdscnt; | 911 | spc.fwdscnt = si.fwdscnt; |
912 | sph.spdhcnt = si.spdhcnt; | 912 | sph.spdhcnt = si.spdhcnt; |
913 | sph.spdhmcnt = si.spdhmcnt; | 913 | sph.spdhmcnt = si.spdhmcnt; |
914 | 914 | ||
915 | NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); | 915 | NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); |
916 | NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); | 916 | NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); |
917 | 917 | ||
918 | return nlmsg_end(skb, nlh); | 918 | return nlmsg_end(skb, nlh); |
919 | 919 | ||
920 | nla_put_failure: | 920 | nla_put_failure: |
921 | nlmsg_cancel(skb, nlh); | 921 | nlmsg_cancel(skb, nlh); |
922 | return -EMSGSIZE; | 922 | return -EMSGSIZE; |
923 | } | 923 | } |
924 | 924 | ||
925 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | 925 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
926 | struct nlattr **attrs) | 926 | struct nlattr **attrs) |
927 | { | 927 | { |
928 | struct net *net = sock_net(skb->sk); | 928 | struct net *net = sock_net(skb->sk); |
929 | struct sk_buff *r_skb; | 929 | struct sk_buff *r_skb; |
930 | u32 *flags = nlmsg_data(nlh); | 930 | u32 *flags = nlmsg_data(nlh); |
931 | u32 spid = NETLINK_CB(skb).pid; | 931 | u32 spid = NETLINK_CB(skb).pid; |
932 | u32 seq = nlh->nlmsg_seq; | 932 | u32 seq = nlh->nlmsg_seq; |
933 | 933 | ||
934 | r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC); | 934 | r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC); |
935 | if (r_skb == NULL) | 935 | if (r_skb == NULL) |
936 | return -ENOMEM; | 936 | return -ENOMEM; |
937 | 937 | ||
938 | if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0) | 938 | if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0) |
939 | BUG(); | 939 | BUG(); |
940 | 940 | ||
941 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); | 941 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
942 | } | 942 | } |
943 | 943 | ||
944 | static inline size_t xfrm_sadinfo_msgsize(void) | 944 | static inline size_t xfrm_sadinfo_msgsize(void) |
945 | { | 945 | { |
946 | return NLMSG_ALIGN(4) | 946 | return NLMSG_ALIGN(4) |
947 | + nla_total_size(sizeof(struct xfrmu_sadhinfo)) | 947 | + nla_total_size(sizeof(struct xfrmu_sadhinfo)) |
948 | + nla_total_size(4); /* XFRMA_SAD_CNT */ | 948 | + nla_total_size(4); /* XFRMA_SAD_CNT */ |
949 | } | 949 | } |
950 | 950 | ||
951 | static int build_sadinfo(struct sk_buff *skb, struct net *net, | 951 | static int build_sadinfo(struct sk_buff *skb, struct net *net, |
952 | u32 pid, u32 seq, u32 flags) | 952 | u32 pid, u32 seq, u32 flags) |
953 | { | 953 | { |
954 | struct xfrmk_sadinfo si; | 954 | struct xfrmk_sadinfo si; |
955 | struct xfrmu_sadhinfo sh; | 955 | struct xfrmu_sadhinfo sh; |
956 | struct nlmsghdr *nlh; | 956 | struct nlmsghdr *nlh; |
957 | u32 *f; | 957 | u32 *f; |
958 | 958 | ||
959 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | 959 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
960 | if (nlh == NULL) /* shouldn't really happen ... */ | 960 | if (nlh == NULL) /* shouldn't really happen ... */ |
961 | return -EMSGSIZE; | 961 | return -EMSGSIZE; |
962 | 962 | ||
963 | f = nlmsg_data(nlh); | 963 | f = nlmsg_data(nlh); |
964 | *f = flags; | 964 | *f = flags; |
965 | xfrm_sad_getinfo(net, &si); | 965 | xfrm_sad_getinfo(net, &si); |
966 | 966 | ||
967 | sh.sadhmcnt = si.sadhmcnt; | 967 | sh.sadhmcnt = si.sadhmcnt; |
968 | sh.sadhcnt = si.sadhcnt; | 968 | sh.sadhcnt = si.sadhcnt; |
969 | 969 | ||
970 | NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt); | 970 | NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt); |
971 | NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh); | 971 | NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh); |
972 | 972 | ||
973 | return nlmsg_end(skb, nlh); | 973 | return nlmsg_end(skb, nlh); |
974 | 974 | ||
975 | nla_put_failure: | 975 | nla_put_failure: |
976 | nlmsg_cancel(skb, nlh); | 976 | nlmsg_cancel(skb, nlh); |
977 | return -EMSGSIZE; | 977 | return -EMSGSIZE; |
978 | } | 978 | } |
979 | 979 | ||
980 | static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | 980 | static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
981 | struct nlattr **attrs) | 981 | struct nlattr **attrs) |
982 | { | 982 | { |
983 | struct net *net = sock_net(skb->sk); | 983 | struct net *net = sock_net(skb->sk); |
984 | struct sk_buff *r_skb; | 984 | struct sk_buff *r_skb; |
985 | u32 *flags = nlmsg_data(nlh); | 985 | u32 *flags = nlmsg_data(nlh); |
986 | u32 spid = NETLINK_CB(skb).pid; | 986 | u32 spid = NETLINK_CB(skb).pid; |
987 | u32 seq = nlh->nlmsg_seq; | 987 | u32 seq = nlh->nlmsg_seq; |
988 | 988 | ||
989 | r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC); | 989 | r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC); |
990 | if (r_skb == NULL) | 990 | if (r_skb == NULL) |
991 | return -ENOMEM; | 991 | return -ENOMEM; |
992 | 992 | ||
993 | if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0) | 993 | if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0) |
994 | BUG(); | 994 | BUG(); |
995 | 995 | ||
996 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); | 996 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
997 | } | 997 | } |
998 | 998 | ||
999 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 999 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
1000 | struct nlattr **attrs) | 1000 | struct nlattr **attrs) |
1001 | { | 1001 | { |
1002 | struct net *net = sock_net(skb->sk); | 1002 | struct net *net = sock_net(skb->sk); |
1003 | struct xfrm_usersa_id *p = nlmsg_data(nlh); | 1003 | struct xfrm_usersa_id *p = nlmsg_data(nlh); |
1004 | struct xfrm_state *x; | 1004 | struct xfrm_state *x; |
1005 | struct sk_buff *resp_skb; | 1005 | struct sk_buff *resp_skb; |
1006 | int err = -ESRCH; | 1006 | int err = -ESRCH; |
1007 | 1007 | ||
1008 | x = xfrm_user_state_lookup(net, p, attrs, &err); | 1008 | x = xfrm_user_state_lookup(net, p, attrs, &err); |
1009 | if (x == NULL) | 1009 | if (x == NULL) |
1010 | goto out_noput; | 1010 | goto out_noput; |
1011 | 1011 | ||
1012 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); | 1012 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); |
1013 | if (IS_ERR(resp_skb)) { | 1013 | if (IS_ERR(resp_skb)) { |
1014 | err = PTR_ERR(resp_skb); | 1014 | err = PTR_ERR(resp_skb); |
1015 | } else { | 1015 | } else { |
1016 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); | 1016 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
1017 | } | 1017 | } |
1018 | xfrm_state_put(x); | 1018 | xfrm_state_put(x); |
1019 | out_noput: | 1019 | out_noput: |
1020 | return err; | 1020 | return err; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static int verify_userspi_info(struct xfrm_userspi_info *p) | 1023 | static int verify_userspi_info(struct xfrm_userspi_info *p) |
1024 | { | 1024 | { |
1025 | switch (p->info.id.proto) { | 1025 | switch (p->info.id.proto) { |
1026 | case IPPROTO_AH: | 1026 | case IPPROTO_AH: |
1027 | case IPPROTO_ESP: | 1027 | case IPPROTO_ESP: |
1028 | break; | 1028 | break; |
1029 | 1029 | ||
1030 | case IPPROTO_COMP: | 1030 | case IPPROTO_COMP: |
1031 | /* IPCOMP spi is 16-bits. */ | 1031 | /* IPCOMP spi is 16-bits. */ |
1032 | if (p->max >= 0x10000) | 1032 | if (p->max >= 0x10000) |
1033 | return -EINVAL; | 1033 | return -EINVAL; |
1034 | break; | 1034 | break; |
1035 | 1035 | ||
1036 | default: | 1036 | default: |
1037 | return -EINVAL; | 1037 | return -EINVAL; |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | if (p->min > p->max) | 1040 | if (p->min > p->max) |
1041 | return -EINVAL; | 1041 | return -EINVAL; |
1042 | 1042 | ||
1043 | return 0; | 1043 | return 0; |
1044 | } | 1044 | } |
1045 | 1045 | ||
1046 | static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | 1046 | static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, |
1047 | struct nlattr **attrs) | 1047 | struct nlattr **attrs) |
1048 | { | 1048 | { |
1049 | struct net *net = sock_net(skb->sk); | 1049 | struct net *net = sock_net(skb->sk); |
1050 | struct xfrm_state *x; | 1050 | struct xfrm_state *x; |
1051 | struct xfrm_userspi_info *p; | 1051 | struct xfrm_userspi_info *p; |
1052 | struct sk_buff *resp_skb; | 1052 | struct sk_buff *resp_skb; |
1053 | xfrm_address_t *daddr; | 1053 | xfrm_address_t *daddr; |
1054 | int family; | 1054 | int family; |
1055 | int err; | 1055 | int err; |
1056 | u32 mark; | 1056 | u32 mark; |
1057 | struct xfrm_mark m; | 1057 | struct xfrm_mark m; |
1058 | 1058 | ||
1059 | p = nlmsg_data(nlh); | 1059 | p = nlmsg_data(nlh); |
1060 | err = verify_userspi_info(p); | 1060 | err = verify_userspi_info(p); |
1061 | if (err) | 1061 | if (err) |
1062 | goto out_noput; | 1062 | goto out_noput; |
1063 | 1063 | ||
1064 | family = p->info.family; | 1064 | family = p->info.family; |
1065 | daddr = &p->info.id.daddr; | 1065 | daddr = &p->info.id.daddr; |
1066 | 1066 | ||
1067 | x = NULL; | 1067 | x = NULL; |
1068 | 1068 | ||
1069 | mark = xfrm_mark_get(attrs, &m); | 1069 | mark = xfrm_mark_get(attrs, &m); |
1070 | if (p->info.seq) { | 1070 | if (p->info.seq) { |
1071 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); | 1071 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); |
1072 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { | 1072 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { |
1073 | xfrm_state_put(x); | 1073 | xfrm_state_put(x); |
1074 | x = NULL; | 1074 | x = NULL; |
1075 | } | 1075 | } |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | if (!x) | 1078 | if (!x) |
1079 | x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, | 1079 | x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, |
1080 | p->info.id.proto, daddr, | 1080 | p->info.id.proto, daddr, |
1081 | &p->info.saddr, 1, | 1081 | &p->info.saddr, 1, |
1082 | family); | 1082 | family); |
1083 | err = -ENOENT; | 1083 | err = -ENOENT; |
1084 | if (x == NULL) | 1084 | if (x == NULL) |
1085 | goto out_noput; | 1085 | goto out_noput; |
1086 | 1086 | ||
1087 | err = xfrm_alloc_spi(x, p->min, p->max); | 1087 | err = xfrm_alloc_spi(x, p->min, p->max); |
1088 | if (err) | 1088 | if (err) |
1089 | goto out; | 1089 | goto out; |
1090 | 1090 | ||
1091 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); | 1091 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); |
1092 | if (IS_ERR(resp_skb)) { | 1092 | if (IS_ERR(resp_skb)) { |
1093 | err = PTR_ERR(resp_skb); | 1093 | err = PTR_ERR(resp_skb); |
1094 | goto out; | 1094 | goto out; |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); | 1097 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
1098 | 1098 | ||
1099 | out: | 1099 | out: |
1100 | xfrm_state_put(x); | 1100 | xfrm_state_put(x); |
1101 | out_noput: | 1101 | out_noput: |
1102 | return err; | 1102 | return err; |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | static int verify_policy_dir(u8 dir) | 1105 | static int verify_policy_dir(u8 dir) |
1106 | { | 1106 | { |
1107 | switch (dir) { | 1107 | switch (dir) { |
1108 | case XFRM_POLICY_IN: | 1108 | case XFRM_POLICY_IN: |
1109 | case XFRM_POLICY_OUT: | 1109 | case XFRM_POLICY_OUT: |
1110 | case XFRM_POLICY_FWD: | 1110 | case XFRM_POLICY_FWD: |
1111 | break; | 1111 | break; |
1112 | 1112 | ||
1113 | default: | 1113 | default: |
1114 | return -EINVAL; | 1114 | return -EINVAL; |
1115 | } | 1115 | } |
1116 | 1116 | ||
1117 | return 0; | 1117 | return 0; |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | static int verify_policy_type(u8 type) | 1120 | static int verify_policy_type(u8 type) |
1121 | { | 1121 | { |
1122 | switch (type) { | 1122 | switch (type) { |
1123 | case XFRM_POLICY_TYPE_MAIN: | 1123 | case XFRM_POLICY_TYPE_MAIN: |
1124 | #ifdef CONFIG_XFRM_SUB_POLICY | 1124 | #ifdef CONFIG_XFRM_SUB_POLICY |
1125 | case XFRM_POLICY_TYPE_SUB: | 1125 | case XFRM_POLICY_TYPE_SUB: |
1126 | #endif | 1126 | #endif |
1127 | break; | 1127 | break; |
1128 | 1128 | ||
1129 | default: | 1129 | default: |
1130 | return -EINVAL; | 1130 | return -EINVAL; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | return 0; | 1133 | return 0; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) | 1136 | static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) |
1137 | { | 1137 | { |
1138 | switch (p->share) { | 1138 | switch (p->share) { |
1139 | case XFRM_SHARE_ANY: | 1139 | case XFRM_SHARE_ANY: |
1140 | case XFRM_SHARE_SESSION: | 1140 | case XFRM_SHARE_SESSION: |
1141 | case XFRM_SHARE_USER: | 1141 | case XFRM_SHARE_USER: |
1142 | case XFRM_SHARE_UNIQUE: | 1142 | case XFRM_SHARE_UNIQUE: |
1143 | break; | 1143 | break; |
1144 | 1144 | ||
1145 | default: | 1145 | default: |
1146 | return -EINVAL; | 1146 | return -EINVAL; |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | switch (p->action) { | 1149 | switch (p->action) { |
1150 | case XFRM_POLICY_ALLOW: | 1150 | case XFRM_POLICY_ALLOW: |
1151 | case XFRM_POLICY_BLOCK: | 1151 | case XFRM_POLICY_BLOCK: |
1152 | break; | 1152 | break; |
1153 | 1153 | ||
1154 | default: | 1154 | default: |
1155 | return -EINVAL; | 1155 | return -EINVAL; |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | switch (p->sel.family) { | 1158 | switch (p->sel.family) { |
1159 | case AF_INET: | 1159 | case AF_INET: |
1160 | break; | 1160 | break; |
1161 | 1161 | ||
1162 | case AF_INET6: | 1162 | case AF_INET6: |
1163 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1163 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1164 | break; | 1164 | break; |
1165 | #else | 1165 | #else |
1166 | return -EAFNOSUPPORT; | 1166 | return -EAFNOSUPPORT; |
1167 | #endif | 1167 | #endif |
1168 | 1168 | ||
1169 | default: | 1169 | default: |
1170 | return -EINVAL; | 1170 | return -EINVAL; |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | return verify_policy_dir(p->dir); | 1173 | return verify_policy_dir(p->dir); |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs) | 1176 | static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs) |
1177 | { | 1177 | { |
1178 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1178 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1179 | struct xfrm_user_sec_ctx *uctx; | 1179 | struct xfrm_user_sec_ctx *uctx; |
1180 | 1180 | ||
1181 | if (!rt) | 1181 | if (!rt) |
1182 | return 0; | 1182 | return 0; |
1183 | 1183 | ||
1184 | uctx = nla_data(rt); | 1184 | uctx = nla_data(rt); |
1185 | return security_xfrm_policy_alloc(&pol->security, uctx); | 1185 | return security_xfrm_policy_alloc(&pol->security, uctx); |
1186 | } | 1186 | } |
1187 | 1187 | ||
1188 | static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, | 1188 | static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, |
1189 | int nr) | 1189 | int nr) |
1190 | { | 1190 | { |
1191 | int i; | 1191 | int i; |
1192 | 1192 | ||
1193 | xp->xfrm_nr = nr; | 1193 | xp->xfrm_nr = nr; |
1194 | for (i = 0; i < nr; i++, ut++) { | 1194 | for (i = 0; i < nr; i++, ut++) { |
1195 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; | 1195 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; |
1196 | 1196 | ||
1197 | memcpy(&t->id, &ut->id, sizeof(struct xfrm_id)); | 1197 | memcpy(&t->id, &ut->id, sizeof(struct xfrm_id)); |
1198 | memcpy(&t->saddr, &ut->saddr, | 1198 | memcpy(&t->saddr, &ut->saddr, |
1199 | sizeof(xfrm_address_t)); | 1199 | sizeof(xfrm_address_t)); |
1200 | t->reqid = ut->reqid; | 1200 | t->reqid = ut->reqid; |
1201 | t->mode = ut->mode; | 1201 | t->mode = ut->mode; |
1202 | t->share = ut->share; | 1202 | t->share = ut->share; |
1203 | t->optional = ut->optional; | 1203 | t->optional = ut->optional; |
1204 | t->aalgos = ut->aalgos; | 1204 | t->aalgos = ut->aalgos; |
1205 | t->ealgos = ut->ealgos; | 1205 | t->ealgos = ut->ealgos; |
1206 | t->calgos = ut->calgos; | 1206 | t->calgos = ut->calgos; |
1207 | /* If all masks are ~0, then we allow all algorithms. */ | 1207 | /* If all masks are ~0, then we allow all algorithms. */ |
1208 | t->allalgs = !~(t->aalgos & t->ealgos & t->calgos); | 1208 | t->allalgs = !~(t->aalgos & t->ealgos & t->calgos); |
1209 | t->encap_family = ut->family; | 1209 | t->encap_family = ut->family; |
1210 | } | 1210 | } |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) | 1213 | static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) |
1214 | { | 1214 | { |
1215 | int i; | 1215 | int i; |
1216 | 1216 | ||
1217 | if (nr > XFRM_MAX_DEPTH) | 1217 | if (nr > XFRM_MAX_DEPTH) |
1218 | return -EINVAL; | 1218 | return -EINVAL; |
1219 | 1219 | ||
1220 | for (i = 0; i < nr; i++) { | 1220 | for (i = 0; i < nr; i++) { |
1221 | /* We never validated the ut->family value, so many | 1221 | /* We never validated the ut->family value, so many |
1222 | * applications simply leave it at zero. The check was | 1222 | * applications simply leave it at zero. The check was |
1223 | * never made and ut->family was ignored because all | 1223 | * never made and ut->family was ignored because all |
1224 | * templates could be assumed to have the same family as | 1224 | * templates could be assumed to have the same family as |
1225 | * the policy itself. Now that we will have ipv4-in-ipv6 | 1225 | * the policy itself. Now that we will have ipv4-in-ipv6 |
1226 | * and ipv6-in-ipv4 tunnels, this is no longer true. | 1226 | * and ipv6-in-ipv4 tunnels, this is no longer true. |
1227 | */ | 1227 | */ |
1228 | if (!ut[i].family) | 1228 | if (!ut[i].family) |
1229 | ut[i].family = family; | 1229 | ut[i].family = family; |
1230 | 1230 | ||
1231 | switch (ut[i].family) { | 1231 | switch (ut[i].family) { |
1232 | case AF_INET: | 1232 | case AF_INET: |
1233 | break; | 1233 | break; |
1234 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1234 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1235 | case AF_INET6: | 1235 | case AF_INET6: |
1236 | break; | 1236 | break; |
1237 | #endif | 1237 | #endif |
1238 | default: | 1238 | default: |
1239 | return -EINVAL; | 1239 | return -EINVAL; |
1240 | } | 1240 | } |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | return 0; | 1243 | return 0; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) | 1246 | static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) |
1247 | { | 1247 | { |
1248 | struct nlattr *rt = attrs[XFRMA_TMPL]; | 1248 | struct nlattr *rt = attrs[XFRMA_TMPL]; |
1249 | 1249 | ||
1250 | if (!rt) { | 1250 | if (!rt) { |
1251 | pol->xfrm_nr = 0; | 1251 | pol->xfrm_nr = 0; |
1252 | } else { | 1252 | } else { |
1253 | struct xfrm_user_tmpl *utmpl = nla_data(rt); | 1253 | struct xfrm_user_tmpl *utmpl = nla_data(rt); |
1254 | int nr = nla_len(rt) / sizeof(*utmpl); | 1254 | int nr = nla_len(rt) / sizeof(*utmpl); |
1255 | int err; | 1255 | int err; |
1256 | 1256 | ||
1257 | err = validate_tmpl(nr, utmpl, pol->family); | 1257 | err = validate_tmpl(nr, utmpl, pol->family); |
1258 | if (err) | 1258 | if (err) |
1259 | return err; | 1259 | return err; |
1260 | 1260 | ||
1261 | copy_templates(pol, utmpl, nr); | 1261 | copy_templates(pol, utmpl, nr); |
1262 | } | 1262 | } |
1263 | return 0; | 1263 | return 0; |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs) | 1266 | static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs) |
1267 | { | 1267 | { |
1268 | struct nlattr *rt = attrs[XFRMA_POLICY_TYPE]; | 1268 | struct nlattr *rt = attrs[XFRMA_POLICY_TYPE]; |
1269 | struct xfrm_userpolicy_type *upt; | 1269 | struct xfrm_userpolicy_type *upt; |
1270 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1270 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1271 | int err; | 1271 | int err; |
1272 | 1272 | ||
1273 | if (rt) { | 1273 | if (rt) { |
1274 | upt = nla_data(rt); | 1274 | upt = nla_data(rt); |
1275 | type = upt->type; | 1275 | type = upt->type; |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | err = verify_policy_type(type); | 1278 | err = verify_policy_type(type); |
1279 | if (err) | 1279 | if (err) |
1280 | return err; | 1280 | return err; |
1281 | 1281 | ||
1282 | *tp = type; | 1282 | *tp = type; |
1283 | return 0; | 1283 | return 0; |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) | 1286 | static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) |
1287 | { | 1287 | { |
1288 | xp->priority = p->priority; | 1288 | xp->priority = p->priority; |
1289 | xp->index = p->index; | 1289 | xp->index = p->index; |
1290 | memcpy(&xp->selector, &p->sel, sizeof(xp->selector)); | 1290 | memcpy(&xp->selector, &p->sel, sizeof(xp->selector)); |
1291 | memcpy(&xp->lft, &p->lft, sizeof(xp->lft)); | 1291 | memcpy(&xp->lft, &p->lft, sizeof(xp->lft)); |
1292 | xp->action = p->action; | 1292 | xp->action = p->action; |
1293 | xp->flags = p->flags; | 1293 | xp->flags = p->flags; |
1294 | xp->family = p->sel.family; | 1294 | xp->family = p->sel.family; |
1295 | /* XXX xp->share = p->share; */ | 1295 | /* XXX xp->share = p->share; */ |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) | 1298 | static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) |
1299 | { | 1299 | { |
1300 | memcpy(&p->sel, &xp->selector, sizeof(p->sel)); | 1300 | memcpy(&p->sel, &xp->selector, sizeof(p->sel)); |
1301 | memcpy(&p->lft, &xp->lft, sizeof(p->lft)); | 1301 | memcpy(&p->lft, &xp->lft, sizeof(p->lft)); |
1302 | memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); | 1302 | memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); |
1303 | p->priority = xp->priority; | 1303 | p->priority = xp->priority; |
1304 | p->index = xp->index; | 1304 | p->index = xp->index; |
1305 | p->sel.family = xp->family; | 1305 | p->sel.family = xp->family; |
1306 | p->dir = dir; | 1306 | p->dir = dir; |
1307 | p->action = xp->action; | 1307 | p->action = xp->action; |
1308 | p->flags = xp->flags; | 1308 | p->flags = xp->flags; |
1309 | p->share = XFRM_SHARE_ANY; /* XXX xp->share */ | 1309 | p->share = XFRM_SHARE_ANY; /* XXX xp->share */ |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) | 1312 | static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) |
1313 | { | 1313 | { |
1314 | struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); | 1314 | struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); |
1315 | int err; | 1315 | int err; |
1316 | 1316 | ||
1317 | if (!xp) { | 1317 | if (!xp) { |
1318 | *errp = -ENOMEM; | 1318 | *errp = -ENOMEM; |
1319 | return NULL; | 1319 | return NULL; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | copy_from_user_policy(xp, p); | 1322 | copy_from_user_policy(xp, p); |
1323 | 1323 | ||
1324 | err = copy_from_user_policy_type(&xp->type, attrs); | 1324 | err = copy_from_user_policy_type(&xp->type, attrs); |
1325 | if (err) | 1325 | if (err) |
1326 | goto error; | 1326 | goto error; |
1327 | 1327 | ||
1328 | if (!(err = copy_from_user_tmpl(xp, attrs))) | 1328 | if (!(err = copy_from_user_tmpl(xp, attrs))) |
1329 | err = copy_from_user_sec_ctx(xp, attrs); | 1329 | err = copy_from_user_sec_ctx(xp, attrs); |
1330 | if (err) | 1330 | if (err) |
1331 | goto error; | 1331 | goto error; |
1332 | 1332 | ||
1333 | xfrm_mark_get(attrs, &xp->mark); | 1333 | xfrm_mark_get(attrs, &xp->mark); |
1334 | 1334 | ||
1335 | return xp; | 1335 | return xp; |
1336 | error: | 1336 | error: |
1337 | *errp = err; | 1337 | *errp = err; |
1338 | xp->walk.dead = 1; | 1338 | xp->walk.dead = 1; |
1339 | xfrm_policy_destroy(xp); | 1339 | xfrm_policy_destroy(xp); |
1340 | return NULL; | 1340 | return NULL; |
1341 | } | 1341 | } |
1342 | 1342 | ||
1343 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1343 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1344 | struct nlattr **attrs) | 1344 | struct nlattr **attrs) |
1345 | { | 1345 | { |
1346 | struct net *net = sock_net(skb->sk); | 1346 | struct net *net = sock_net(skb->sk); |
1347 | struct xfrm_userpolicy_info *p = nlmsg_data(nlh); | 1347 | struct xfrm_userpolicy_info *p = nlmsg_data(nlh); |
1348 | struct xfrm_policy *xp; | 1348 | struct xfrm_policy *xp; |
1349 | struct km_event c; | 1349 | struct km_event c; |
1350 | int err; | 1350 | int err; |
1351 | int excl; | 1351 | int excl; |
1352 | uid_t loginuid = audit_get_loginuid(current); | 1352 | uid_t loginuid = audit_get_loginuid(current); |
1353 | u32 sessionid = audit_get_sessionid(current); | 1353 | u32 sessionid = audit_get_sessionid(current); |
1354 | u32 sid; | 1354 | u32 sid; |
1355 | 1355 | ||
1356 | err = verify_newpolicy_info(p); | 1356 | err = verify_newpolicy_info(p); |
1357 | if (err) | 1357 | if (err) |
1358 | return err; | 1358 | return err; |
1359 | err = verify_sec_ctx_len(attrs); | 1359 | err = verify_sec_ctx_len(attrs); |
1360 | if (err) | 1360 | if (err) |
1361 | return err; | 1361 | return err; |
1362 | 1362 | ||
1363 | xp = xfrm_policy_construct(net, p, attrs, &err); | 1363 | xp = xfrm_policy_construct(net, p, attrs, &err); |
1364 | if (!xp) | 1364 | if (!xp) |
1365 | return err; | 1365 | return err; |
1366 | 1366 | ||
1367 | /* shouldn't excl be based on nlh flags?? | 1367 | /* shouldn't excl be based on nlh flags?? |
1368 | * Aha! this is anti-netlink really i.e more pfkey derived | 1368 | * Aha! this is anti-netlink really i.e more pfkey derived |
1369 | * in netlink excl is a flag and you wouldnt need | 1369 | * in netlink excl is a flag and you wouldnt need |
1370 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1370 | * a type XFRM_MSG_UPDPOLICY - JHS */ |
1371 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; | 1371 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; |
1372 | err = xfrm_policy_insert(p->dir, xp, excl); | 1372 | err = xfrm_policy_insert(p->dir, xp, excl); |
1373 | security_task_getsecid(current, &sid); | 1373 | security_task_getsecid(current, &sid); |
1374 | xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid); | 1374 | xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid); |
1375 | 1375 | ||
1376 | if (err) { | 1376 | if (err) { |
1377 | security_xfrm_policy_free(xp->security); | 1377 | security_xfrm_policy_free(xp->security); |
1378 | kfree(xp); | 1378 | kfree(xp); |
1379 | return err; | 1379 | return err; |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | c.event = nlh->nlmsg_type; | 1382 | c.event = nlh->nlmsg_type; |
1383 | c.seq = nlh->nlmsg_seq; | 1383 | c.seq = nlh->nlmsg_seq; |
1384 | c.pid = nlh->nlmsg_pid; | 1384 | c.pid = nlh->nlmsg_pid; |
1385 | km_policy_notify(xp, p->dir, &c); | 1385 | km_policy_notify(xp, p->dir, &c); |
1386 | 1386 | ||
1387 | xfrm_pol_put(xp); | 1387 | xfrm_pol_put(xp); |
1388 | 1388 | ||
1389 | return 0; | 1389 | return 0; |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) | 1392 | static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) |
1393 | { | 1393 | { |
1394 | struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH]; | 1394 | struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH]; |
1395 | int i; | 1395 | int i; |
1396 | 1396 | ||
1397 | if (xp->xfrm_nr == 0) | 1397 | if (xp->xfrm_nr == 0) |
1398 | return 0; | 1398 | return 0; |
1399 | 1399 | ||
1400 | for (i = 0; i < xp->xfrm_nr; i++) { | 1400 | for (i = 0; i < xp->xfrm_nr; i++) { |
1401 | struct xfrm_user_tmpl *up = &vec[i]; | 1401 | struct xfrm_user_tmpl *up = &vec[i]; |
1402 | struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; | 1402 | struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; |
1403 | 1403 | ||
1404 | memcpy(&up->id, &kp->id, sizeof(up->id)); | 1404 | memcpy(&up->id, &kp->id, sizeof(up->id)); |
1405 | up->family = kp->encap_family; | 1405 | up->family = kp->encap_family; |
1406 | memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); | 1406 | memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); |
1407 | up->reqid = kp->reqid; | 1407 | up->reqid = kp->reqid; |
1408 | up->mode = kp->mode; | 1408 | up->mode = kp->mode; |
1409 | up->share = kp->share; | 1409 | up->share = kp->share; |
1410 | up->optional = kp->optional; | 1410 | up->optional = kp->optional; |
1411 | up->aalgos = kp->aalgos; | 1411 | up->aalgos = kp->aalgos; |
1412 | up->ealgos = kp->ealgos; | 1412 | up->ealgos = kp->ealgos; |
1413 | up->calgos = kp->calgos; | 1413 | up->calgos = kp->calgos; |
1414 | } | 1414 | } |
1415 | 1415 | ||
1416 | return nla_put(skb, XFRMA_TMPL, | 1416 | return nla_put(skb, XFRMA_TMPL, |
1417 | sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec); | 1417 | sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec); |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb) | 1420 | static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb) |
1421 | { | 1421 | { |
1422 | if (x->security) { | 1422 | if (x->security) { |
1423 | return copy_sec_ctx(x->security, skb); | 1423 | return copy_sec_ctx(x->security, skb); |
1424 | } | 1424 | } |
1425 | return 0; | 1425 | return 0; |
1426 | } | 1426 | } |
1427 | 1427 | ||
1428 | static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) | 1428 | static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) |
1429 | { | 1429 | { |
1430 | if (xp->security) { | 1430 | if (xp->security) { |
1431 | return copy_sec_ctx(xp->security, skb); | 1431 | return copy_sec_ctx(xp->security, skb); |
1432 | } | 1432 | } |
1433 | return 0; | 1433 | return 0; |
1434 | } | 1434 | } |
1435 | static inline size_t userpolicy_type_attrsize(void) | 1435 | static inline size_t userpolicy_type_attrsize(void) |
1436 | { | 1436 | { |
1437 | #ifdef CONFIG_XFRM_SUB_POLICY | 1437 | #ifdef CONFIG_XFRM_SUB_POLICY |
1438 | return nla_total_size(sizeof(struct xfrm_userpolicy_type)); | 1438 | return nla_total_size(sizeof(struct xfrm_userpolicy_type)); |
1439 | #else | 1439 | #else |
1440 | return 0; | 1440 | return 0; |
1441 | #endif | 1441 | #endif |
1442 | } | 1442 | } |
1443 | 1443 | ||
1444 | #ifdef CONFIG_XFRM_SUB_POLICY | 1444 | #ifdef CONFIG_XFRM_SUB_POLICY |
1445 | static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) | 1445 | static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) |
1446 | { | 1446 | { |
1447 | struct xfrm_userpolicy_type upt = { | 1447 | struct xfrm_userpolicy_type upt = { |
1448 | .type = type, | 1448 | .type = type, |
1449 | }; | 1449 | }; |
1450 | 1450 | ||
1451 | return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); | 1451 | return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | #else | 1454 | #else |
1455 | static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb) | 1455 | static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb) |
1456 | { | 1456 | { |
1457 | return 0; | 1457 | return 0; |
1458 | } | 1458 | } |
1459 | #endif | 1459 | #endif |
1460 | 1460 | ||
1461 | static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) | 1461 | static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) |
1462 | { | 1462 | { |
1463 | struct xfrm_dump_info *sp = ptr; | 1463 | struct xfrm_dump_info *sp = ptr; |
1464 | struct xfrm_userpolicy_info *p; | 1464 | struct xfrm_userpolicy_info *p; |
1465 | struct sk_buff *in_skb = sp->in_skb; | 1465 | struct sk_buff *in_skb = sp->in_skb; |
1466 | struct sk_buff *skb = sp->out_skb; | 1466 | struct sk_buff *skb = sp->out_skb; |
1467 | struct nlmsghdr *nlh; | 1467 | struct nlmsghdr *nlh; |
1468 | 1468 | ||
1469 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | 1469 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, |
1470 | XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags); | 1470 | XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags); |
1471 | if (nlh == NULL) | 1471 | if (nlh == NULL) |
1472 | return -EMSGSIZE; | 1472 | return -EMSGSIZE; |
1473 | 1473 | ||
1474 | p = nlmsg_data(nlh); | 1474 | p = nlmsg_data(nlh); |
1475 | copy_to_user_policy(xp, p, dir); | 1475 | copy_to_user_policy(xp, p, dir); |
1476 | if (copy_to_user_tmpl(xp, skb) < 0) | 1476 | if (copy_to_user_tmpl(xp, skb) < 0) |
1477 | goto nlmsg_failure; | 1477 | goto nlmsg_failure; |
1478 | if (copy_to_user_sec_ctx(xp, skb)) | 1478 | if (copy_to_user_sec_ctx(xp, skb)) |
1479 | goto nlmsg_failure; | 1479 | goto nlmsg_failure; |
1480 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 1480 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
1481 | goto nlmsg_failure; | 1481 | goto nlmsg_failure; |
1482 | if (xfrm_mark_put(skb, &xp->mark)) | 1482 | if (xfrm_mark_put(skb, &xp->mark)) |
1483 | goto nla_put_failure; | 1483 | goto nla_put_failure; |
1484 | 1484 | ||
1485 | nlmsg_end(skb, nlh); | 1485 | nlmsg_end(skb, nlh); |
1486 | return 0; | 1486 | return 0; |
1487 | 1487 | ||
1488 | nla_put_failure: | 1488 | nla_put_failure: |
1489 | nlmsg_failure: | 1489 | nlmsg_failure: |
1490 | nlmsg_cancel(skb, nlh); | 1490 | nlmsg_cancel(skb, nlh); |
1491 | return -EMSGSIZE; | 1491 | return -EMSGSIZE; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static int xfrm_dump_policy_done(struct netlink_callback *cb) | 1494 | static int xfrm_dump_policy_done(struct netlink_callback *cb) |
1495 | { | 1495 | { |
1496 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; | 1496 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; |
1497 | 1497 | ||
1498 | xfrm_policy_walk_done(walk); | 1498 | xfrm_policy_walk_done(walk); |
1499 | return 0; | 1499 | return 0; |
1500 | } | 1500 | } |
1501 | 1501 | ||
1502 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) | 1502 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) |
1503 | { | 1503 | { |
1504 | struct net *net = sock_net(skb->sk); | 1504 | struct net *net = sock_net(skb->sk); |
1505 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; | 1505 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; |
1506 | struct xfrm_dump_info info; | 1506 | struct xfrm_dump_info info; |
1507 | 1507 | ||
1508 | BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > | 1508 | BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > |
1509 | sizeof(cb->args) - sizeof(cb->args[0])); | 1509 | sizeof(cb->args) - sizeof(cb->args[0])); |
1510 | 1510 | ||
1511 | info.in_skb = cb->skb; | 1511 | info.in_skb = cb->skb; |
1512 | info.out_skb = skb; | 1512 | info.out_skb = skb; |
1513 | info.nlmsg_seq = cb->nlh->nlmsg_seq; | 1513 | info.nlmsg_seq = cb->nlh->nlmsg_seq; |
1514 | info.nlmsg_flags = NLM_F_MULTI; | 1514 | info.nlmsg_flags = NLM_F_MULTI; |
1515 | 1515 | ||
1516 | if (!cb->args[0]) { | 1516 | if (!cb->args[0]) { |
1517 | cb->args[0] = 1; | 1517 | cb->args[0] = 1; |
1518 | xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); | 1518 | xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); | 1521 | (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); |
1522 | 1522 | ||
1523 | return skb->len; | 1523 | return skb->len; |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, | 1526 | static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, |
1527 | struct xfrm_policy *xp, | 1527 | struct xfrm_policy *xp, |
1528 | int dir, u32 seq) | 1528 | int dir, u32 seq) |
1529 | { | 1529 | { |
1530 | struct xfrm_dump_info info; | 1530 | struct xfrm_dump_info info; |
1531 | struct sk_buff *skb; | 1531 | struct sk_buff *skb; |
1532 | 1532 | ||
1533 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1533 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
1534 | if (!skb) | 1534 | if (!skb) |
1535 | return ERR_PTR(-ENOMEM); | 1535 | return ERR_PTR(-ENOMEM); |
1536 | 1536 | ||
1537 | info.in_skb = in_skb; | 1537 | info.in_skb = in_skb; |
1538 | info.out_skb = skb; | 1538 | info.out_skb = skb; |
1539 | info.nlmsg_seq = seq; | 1539 | info.nlmsg_seq = seq; |
1540 | info.nlmsg_flags = 0; | 1540 | info.nlmsg_flags = 0; |
1541 | 1541 | ||
1542 | if (dump_one_policy(xp, dir, 0, &info) < 0) { | 1542 | if (dump_one_policy(xp, dir, 0, &info) < 0) { |
1543 | kfree_skb(skb); | 1543 | kfree_skb(skb); |
1544 | return NULL; | 1544 | return NULL; |
1545 | } | 1545 | } |
1546 | 1546 | ||
1547 | return skb; | 1547 | return skb; |
1548 | } | 1548 | } |
1549 | 1549 | ||
1550 | static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1550 | static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1551 | struct nlattr **attrs) | 1551 | struct nlattr **attrs) |
1552 | { | 1552 | { |
1553 | struct net *net = sock_net(skb->sk); | 1553 | struct net *net = sock_net(skb->sk); |
1554 | struct xfrm_policy *xp; | 1554 | struct xfrm_policy *xp; |
1555 | struct xfrm_userpolicy_id *p; | 1555 | struct xfrm_userpolicy_id *p; |
1556 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1556 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1557 | int err; | 1557 | int err; |
1558 | struct km_event c; | 1558 | struct km_event c; |
1559 | int delete; | 1559 | int delete; |
1560 | struct xfrm_mark m; | 1560 | struct xfrm_mark m; |
1561 | u32 mark = xfrm_mark_get(attrs, &m); | 1561 | u32 mark = xfrm_mark_get(attrs, &m); |
1562 | 1562 | ||
1563 | p = nlmsg_data(nlh); | 1563 | p = nlmsg_data(nlh); |
1564 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; | 1564 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; |
1565 | 1565 | ||
1566 | err = copy_from_user_policy_type(&type, attrs); | 1566 | err = copy_from_user_policy_type(&type, attrs); |
1567 | if (err) | 1567 | if (err) |
1568 | return err; | 1568 | return err; |
1569 | 1569 | ||
1570 | err = verify_policy_dir(p->dir); | 1570 | err = verify_policy_dir(p->dir); |
1571 | if (err) | 1571 | if (err) |
1572 | return err; | 1572 | return err; |
1573 | 1573 | ||
1574 | if (p->index) | 1574 | if (p->index) |
1575 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); | 1575 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); |
1576 | else { | 1576 | else { |
1577 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1577 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1578 | struct xfrm_sec_ctx *ctx; | 1578 | struct xfrm_sec_ctx *ctx; |
1579 | 1579 | ||
1580 | err = verify_sec_ctx_len(attrs); | 1580 | err = verify_sec_ctx_len(attrs); |
1581 | if (err) | 1581 | if (err) |
1582 | return err; | 1582 | return err; |
1583 | 1583 | ||
1584 | ctx = NULL; | 1584 | ctx = NULL; |
1585 | if (rt) { | 1585 | if (rt) { |
1586 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1586 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
1587 | 1587 | ||
1588 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1588 | err = security_xfrm_policy_alloc(&ctx, uctx); |
1589 | if (err) | 1589 | if (err) |
1590 | return err; | 1590 | return err; |
1591 | } | 1591 | } |
1592 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, | 1592 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, |
1593 | ctx, delete, &err); | 1593 | ctx, delete, &err); |
1594 | security_xfrm_policy_free(ctx); | 1594 | security_xfrm_policy_free(ctx); |
1595 | } | 1595 | } |
1596 | if (xp == NULL) | 1596 | if (xp == NULL) |
1597 | return -ENOENT; | 1597 | return -ENOENT; |
1598 | 1598 | ||
1599 | if (!delete) { | 1599 | if (!delete) { |
1600 | struct sk_buff *resp_skb; | 1600 | struct sk_buff *resp_skb; |
1601 | 1601 | ||
1602 | resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq); | 1602 | resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq); |
1603 | if (IS_ERR(resp_skb)) { | 1603 | if (IS_ERR(resp_skb)) { |
1604 | err = PTR_ERR(resp_skb); | 1604 | err = PTR_ERR(resp_skb); |
1605 | } else { | 1605 | } else { |
1606 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, | 1606 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, |
1607 | NETLINK_CB(skb).pid); | 1607 | NETLINK_CB(skb).pid); |
1608 | } | 1608 | } |
1609 | } else { | 1609 | } else { |
1610 | uid_t loginuid = audit_get_loginuid(current); | 1610 | uid_t loginuid = audit_get_loginuid(current); |
1611 | u32 sessionid = audit_get_sessionid(current); | 1611 | u32 sessionid = audit_get_sessionid(current); |
1612 | u32 sid; | 1612 | u32 sid; |
1613 | 1613 | ||
1614 | security_task_getsecid(current, &sid); | 1614 | security_task_getsecid(current, &sid); |
1615 | xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid, | 1615 | xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid, |
1616 | sid); | 1616 | sid); |
1617 | 1617 | ||
1618 | if (err != 0) | 1618 | if (err != 0) |
1619 | goto out; | 1619 | goto out; |
1620 | 1620 | ||
1621 | c.data.byid = p->index; | 1621 | c.data.byid = p->index; |
1622 | c.event = nlh->nlmsg_type; | 1622 | c.event = nlh->nlmsg_type; |
1623 | c.seq = nlh->nlmsg_seq; | 1623 | c.seq = nlh->nlmsg_seq; |
1624 | c.pid = nlh->nlmsg_pid; | 1624 | c.pid = nlh->nlmsg_pid; |
1625 | km_policy_notify(xp, p->dir, &c); | 1625 | km_policy_notify(xp, p->dir, &c); |
1626 | } | 1626 | } |
1627 | 1627 | ||
1628 | out: | 1628 | out: |
1629 | xfrm_pol_put(xp); | 1629 | xfrm_pol_put(xp); |
1630 | return err; | 1630 | return err; |
1631 | } | 1631 | } |
1632 | 1632 | ||
1633 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 1633 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
1634 | struct nlattr **attrs) | 1634 | struct nlattr **attrs) |
1635 | { | 1635 | { |
1636 | struct net *net = sock_net(skb->sk); | 1636 | struct net *net = sock_net(skb->sk); |
1637 | struct km_event c; | 1637 | struct km_event c; |
1638 | struct xfrm_usersa_flush *p = nlmsg_data(nlh); | 1638 | struct xfrm_usersa_flush *p = nlmsg_data(nlh); |
1639 | struct xfrm_audit audit_info; | 1639 | struct xfrm_audit audit_info; |
1640 | int err; | 1640 | int err; |
1641 | 1641 | ||
1642 | audit_info.loginuid = audit_get_loginuid(current); | 1642 | audit_info.loginuid = audit_get_loginuid(current); |
1643 | audit_info.sessionid = audit_get_sessionid(current); | 1643 | audit_info.sessionid = audit_get_sessionid(current); |
1644 | security_task_getsecid(current, &audit_info.secid); | 1644 | security_task_getsecid(current, &audit_info.secid); |
1645 | err = xfrm_state_flush(net, p->proto, &audit_info); | 1645 | err = xfrm_state_flush(net, p->proto, &audit_info); |
1646 | if (err) { | 1646 | if (err) { |
1647 | if (err == -ESRCH) /* empty table */ | 1647 | if (err == -ESRCH) /* empty table */ |
1648 | return 0; | 1648 | return 0; |
1649 | return err; | 1649 | return err; |
1650 | } | 1650 | } |
1651 | c.data.proto = p->proto; | 1651 | c.data.proto = p->proto; |
1652 | c.event = nlh->nlmsg_type; | 1652 | c.event = nlh->nlmsg_type; |
1653 | c.seq = nlh->nlmsg_seq; | 1653 | c.seq = nlh->nlmsg_seq; |
1654 | c.pid = nlh->nlmsg_pid; | 1654 | c.pid = nlh->nlmsg_pid; |
1655 | c.net = net; | 1655 | c.net = net; |
1656 | km_state_notify(NULL, &c); | 1656 | km_state_notify(NULL, &c); |
1657 | 1657 | ||
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | 1660 | ||
1661 | static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x) | 1661 | static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x) |
1662 | { | 1662 | { |
1663 | size_t replay_size = x->replay_esn ? | 1663 | size_t replay_size = x->replay_esn ? |
1664 | xfrm_replay_state_esn_len(x->replay_esn) : | 1664 | xfrm_replay_state_esn_len(x->replay_esn) : |
1665 | sizeof(struct xfrm_replay_state); | 1665 | sizeof(struct xfrm_replay_state); |
1666 | 1666 | ||
1667 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) | 1667 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) |
1668 | + nla_total_size(replay_size) | 1668 | + nla_total_size(replay_size) |
1669 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) | 1669 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) |
1670 | + nla_total_size(sizeof(struct xfrm_mark)) | 1670 | + nla_total_size(sizeof(struct xfrm_mark)) |
1671 | + nla_total_size(4) /* XFRM_AE_RTHR */ | 1671 | + nla_total_size(4) /* XFRM_AE_RTHR */ |
1672 | + nla_total_size(4); /* XFRM_AE_ETHR */ | 1672 | + nla_total_size(4); /* XFRM_AE_ETHR */ |
1673 | } | 1673 | } |
1674 | 1674 | ||
1675 | static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) | 1675 | static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
1676 | { | 1676 | { |
1677 | struct xfrm_aevent_id *id; | 1677 | struct xfrm_aevent_id *id; |
1678 | struct nlmsghdr *nlh; | 1678 | struct nlmsghdr *nlh; |
1679 | 1679 | ||
1680 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0); | 1680 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0); |
1681 | if (nlh == NULL) | 1681 | if (nlh == NULL) |
1682 | return -EMSGSIZE; | 1682 | return -EMSGSIZE; |
1683 | 1683 | ||
1684 | id = nlmsg_data(nlh); | 1684 | id = nlmsg_data(nlh); |
1685 | memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr)); | 1685 | memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr)); |
1686 | id->sa_id.spi = x->id.spi; | 1686 | id->sa_id.spi = x->id.spi; |
1687 | id->sa_id.family = x->props.family; | 1687 | id->sa_id.family = x->props.family; |
1688 | id->sa_id.proto = x->id.proto; | 1688 | id->sa_id.proto = x->id.proto; |
1689 | memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr)); | 1689 | memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr)); |
1690 | id->reqid = x->props.reqid; | 1690 | id->reqid = x->props.reqid; |
1691 | id->flags = c->data.aevent; | 1691 | id->flags = c->data.aevent; |
1692 | 1692 | ||
1693 | if (x->replay_esn) | 1693 | if (x->replay_esn) |
1694 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, | 1694 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, |
1695 | xfrm_replay_state_esn_len(x->replay_esn), | 1695 | xfrm_replay_state_esn_len(x->replay_esn), |
1696 | x->replay_esn); | 1696 | x->replay_esn); |
1697 | else | 1697 | else |
1698 | NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); | 1698 | NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); |
1699 | 1699 | ||
1700 | NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); | 1700 | NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); |
1701 | 1701 | ||
1702 | if (id->flags & XFRM_AE_RTHR) | 1702 | if (id->flags & XFRM_AE_RTHR) |
1703 | NLA_PUT_U32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff); | 1703 | NLA_PUT_U32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff); |
1704 | 1704 | ||
1705 | if (id->flags & XFRM_AE_ETHR) | 1705 | if (id->flags & XFRM_AE_ETHR) |
1706 | NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, | 1706 | NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, |
1707 | x->replay_maxage * 10 / HZ); | 1707 | x->replay_maxage * 10 / HZ); |
1708 | 1708 | ||
1709 | if (xfrm_mark_put(skb, &x->mark)) | 1709 | if (xfrm_mark_put(skb, &x->mark)) |
1710 | goto nla_put_failure; | 1710 | goto nla_put_failure; |
1711 | 1711 | ||
1712 | return nlmsg_end(skb, nlh); | 1712 | return nlmsg_end(skb, nlh); |
1713 | 1713 | ||
1714 | nla_put_failure: | 1714 | nla_put_failure: |
1715 | nlmsg_cancel(skb, nlh); | 1715 | nlmsg_cancel(skb, nlh); |
1716 | return -EMSGSIZE; | 1716 | return -EMSGSIZE; |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | 1719 | static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
1720 | struct nlattr **attrs) | 1720 | struct nlattr **attrs) |
1721 | { | 1721 | { |
1722 | struct net *net = sock_net(skb->sk); | 1722 | struct net *net = sock_net(skb->sk); |
1723 | struct xfrm_state *x; | 1723 | struct xfrm_state *x; |
1724 | struct sk_buff *r_skb; | 1724 | struct sk_buff *r_skb; |
1725 | int err; | 1725 | int err; |
1726 | struct km_event c; | 1726 | struct km_event c; |
1727 | u32 mark; | 1727 | u32 mark; |
1728 | struct xfrm_mark m; | 1728 | struct xfrm_mark m; |
1729 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1729 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1730 | struct xfrm_usersa_id *id = &p->sa_id; | 1730 | struct xfrm_usersa_id *id = &p->sa_id; |
1731 | 1731 | ||
1732 | mark = xfrm_mark_get(attrs, &m); | 1732 | mark = xfrm_mark_get(attrs, &m); |
1733 | 1733 | ||
1734 | x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); | 1734 | x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); |
1735 | if (x == NULL) | 1735 | if (x == NULL) |
1736 | return -ESRCH; | 1736 | return -ESRCH; |
1737 | 1737 | ||
1738 | r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); | 1738 | r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); |
1739 | if (r_skb == NULL) { | 1739 | if (r_skb == NULL) { |
1740 | xfrm_state_put(x); | 1740 | xfrm_state_put(x); |
1741 | return -ENOMEM; | 1741 | return -ENOMEM; |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | /* | 1744 | /* |
1745 | * XXX: is this lock really needed - none of the other | 1745 | * XXX: is this lock really needed - none of the other |
1746 | * gets lock (the concern is things getting updated | 1746 | * gets lock (the concern is things getting updated |
1747 | * while we are still reading) - jhs | 1747 | * while we are still reading) - jhs |
1748 | */ | 1748 | */ |
1749 | spin_lock_bh(&x->lock); | 1749 | spin_lock_bh(&x->lock); |
1750 | c.data.aevent = p->flags; | 1750 | c.data.aevent = p->flags; |
1751 | c.seq = nlh->nlmsg_seq; | 1751 | c.seq = nlh->nlmsg_seq; |
1752 | c.pid = nlh->nlmsg_pid; | 1752 | c.pid = nlh->nlmsg_pid; |
1753 | 1753 | ||
1754 | if (build_aevent(r_skb, x, &c) < 0) | 1754 | if (build_aevent(r_skb, x, &c) < 0) |
1755 | BUG(); | 1755 | BUG(); |
1756 | err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid); | 1756 | err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid); |
1757 | spin_unlock_bh(&x->lock); | 1757 | spin_unlock_bh(&x->lock); |
1758 | xfrm_state_put(x); | 1758 | xfrm_state_put(x); |
1759 | return err; | 1759 | return err; |
1760 | } | 1760 | } |
1761 | 1761 | ||
1762 | static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | 1762 | static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
1763 | struct nlattr **attrs) | 1763 | struct nlattr **attrs) |
1764 | { | 1764 | { |
1765 | struct net *net = sock_net(skb->sk); | 1765 | struct net *net = sock_net(skb->sk); |
1766 | struct xfrm_state *x; | 1766 | struct xfrm_state *x; |
1767 | struct km_event c; | 1767 | struct km_event c; |
1768 | int err = - EINVAL; | 1768 | int err = - EINVAL; |
1769 | u32 mark = 0; | 1769 | u32 mark = 0; |
1770 | struct xfrm_mark m; | 1770 | struct xfrm_mark m; |
1771 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1771 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1772 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 1772 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
1773 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; | 1773 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; |
1774 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 1774 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
1775 | 1775 | ||
1776 | if (!lt && !rp && !re) | 1776 | if (!lt && !rp && !re) |
1777 | return err; | 1777 | return err; |
1778 | 1778 | ||
1779 | /* pedantic mode - thou shalt sayeth replaceth */ | 1779 | /* pedantic mode - thou shalt sayeth replaceth */ |
1780 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) | 1780 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) |
1781 | return err; | 1781 | return err; |
1782 | 1782 | ||
1783 | mark = xfrm_mark_get(attrs, &m); | 1783 | mark = xfrm_mark_get(attrs, &m); |
1784 | 1784 | ||
1785 | x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); | 1785 | x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); |
1786 | if (x == NULL) | 1786 | if (x == NULL) |
1787 | return -ESRCH; | 1787 | return -ESRCH; |
1788 | 1788 | ||
1789 | if (x->km.state != XFRM_STATE_VALID) | 1789 | if (x->km.state != XFRM_STATE_VALID) |
1790 | goto out; | 1790 | goto out; |
1791 | 1791 | ||
1792 | err = xfrm_replay_verify_len(x->replay_esn, rp); | 1792 | err = xfrm_replay_verify_len(x->replay_esn, rp); |
1793 | if (err) | 1793 | if (err) |
1794 | goto out; | 1794 | goto out; |
1795 | 1795 | ||
1796 | spin_lock_bh(&x->lock); | 1796 | spin_lock_bh(&x->lock); |
1797 | xfrm_update_ae_params(x, attrs); | 1797 | xfrm_update_ae_params(x, attrs); |
1798 | spin_unlock_bh(&x->lock); | 1798 | spin_unlock_bh(&x->lock); |
1799 | 1799 | ||
1800 | c.event = nlh->nlmsg_type; | 1800 | c.event = nlh->nlmsg_type; |
1801 | c.seq = nlh->nlmsg_seq; | 1801 | c.seq = nlh->nlmsg_seq; |
1802 | c.pid = nlh->nlmsg_pid; | 1802 | c.pid = nlh->nlmsg_pid; |
1803 | c.data.aevent = XFRM_AE_CU; | 1803 | c.data.aevent = XFRM_AE_CU; |
1804 | km_state_notify(x, &c); | 1804 | km_state_notify(x, &c); |
1805 | err = 0; | 1805 | err = 0; |
1806 | out: | 1806 | out: |
1807 | xfrm_state_put(x); | 1807 | xfrm_state_put(x); |
1808 | return err; | 1808 | return err; |
1809 | } | 1809 | } |
1810 | 1810 | ||
1811 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1811 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1812 | struct nlattr **attrs) | 1812 | struct nlattr **attrs) |
1813 | { | 1813 | { |
1814 | struct net *net = sock_net(skb->sk); | 1814 | struct net *net = sock_net(skb->sk); |
1815 | struct km_event c; | 1815 | struct km_event c; |
1816 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1816 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1817 | int err; | 1817 | int err; |
1818 | struct xfrm_audit audit_info; | 1818 | struct xfrm_audit audit_info; |
1819 | 1819 | ||
1820 | err = copy_from_user_policy_type(&type, attrs); | 1820 | err = copy_from_user_policy_type(&type, attrs); |
1821 | if (err) | 1821 | if (err) |
1822 | return err; | 1822 | return err; |
1823 | 1823 | ||
1824 | audit_info.loginuid = audit_get_loginuid(current); | 1824 | audit_info.loginuid = audit_get_loginuid(current); |
1825 | audit_info.sessionid = audit_get_sessionid(current); | 1825 | audit_info.sessionid = audit_get_sessionid(current); |
1826 | security_task_getsecid(current, &audit_info.secid); | 1826 | security_task_getsecid(current, &audit_info.secid); |
1827 | err = xfrm_policy_flush(net, type, &audit_info); | 1827 | err = xfrm_policy_flush(net, type, &audit_info); |
1828 | if (err) { | 1828 | if (err) { |
1829 | if (err == -ESRCH) /* empty table */ | 1829 | if (err == -ESRCH) /* empty table */ |
1830 | return 0; | 1830 | return 0; |
1831 | return err; | 1831 | return err; |
1832 | } | 1832 | } |
1833 | 1833 | ||
1834 | c.data.type = type; | 1834 | c.data.type = type; |
1835 | c.event = nlh->nlmsg_type; | 1835 | c.event = nlh->nlmsg_type; |
1836 | c.seq = nlh->nlmsg_seq; | 1836 | c.seq = nlh->nlmsg_seq; |
1837 | c.pid = nlh->nlmsg_pid; | 1837 | c.pid = nlh->nlmsg_pid; |
1838 | c.net = net; | 1838 | c.net = net; |
1839 | km_policy_notify(NULL, 0, &c); | 1839 | km_policy_notify(NULL, 0, &c); |
1840 | return 0; | 1840 | return 0; |
1841 | } | 1841 | } |
1842 | 1842 | ||
1843 | static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1843 | static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1844 | struct nlattr **attrs) | 1844 | struct nlattr **attrs) |
1845 | { | 1845 | { |
1846 | struct net *net = sock_net(skb->sk); | 1846 | struct net *net = sock_net(skb->sk); |
1847 | struct xfrm_policy *xp; | 1847 | struct xfrm_policy *xp; |
1848 | struct xfrm_user_polexpire *up = nlmsg_data(nlh); | 1848 | struct xfrm_user_polexpire *up = nlmsg_data(nlh); |
1849 | struct xfrm_userpolicy_info *p = &up->pol; | 1849 | struct xfrm_userpolicy_info *p = &up->pol; |
1850 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1850 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1851 | int err = -ENOENT; | 1851 | int err = -ENOENT; |
1852 | struct xfrm_mark m; | 1852 | struct xfrm_mark m; |
1853 | u32 mark = xfrm_mark_get(attrs, &m); | 1853 | u32 mark = xfrm_mark_get(attrs, &m); |
1854 | 1854 | ||
1855 | err = copy_from_user_policy_type(&type, attrs); | 1855 | err = copy_from_user_policy_type(&type, attrs); |
1856 | if (err) | 1856 | if (err) |
1857 | return err; | 1857 | return err; |
1858 | 1858 | ||
1859 | err = verify_policy_dir(p->dir); | 1859 | err = verify_policy_dir(p->dir); |
1860 | if (err) | 1860 | if (err) |
1861 | return err; | 1861 | return err; |
1862 | 1862 | ||
1863 | if (p->index) | 1863 | if (p->index) |
1864 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); | 1864 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); |
1865 | else { | 1865 | else { |
1866 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1866 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1867 | struct xfrm_sec_ctx *ctx; | 1867 | struct xfrm_sec_ctx *ctx; |
1868 | 1868 | ||
1869 | err = verify_sec_ctx_len(attrs); | 1869 | err = verify_sec_ctx_len(attrs); |
1870 | if (err) | 1870 | if (err) |
1871 | return err; | 1871 | return err; |
1872 | 1872 | ||
1873 | ctx = NULL; | 1873 | ctx = NULL; |
1874 | if (rt) { | 1874 | if (rt) { |
1875 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1875 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
1876 | 1876 | ||
1877 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1877 | err = security_xfrm_policy_alloc(&ctx, uctx); |
1878 | if (err) | 1878 | if (err) |
1879 | return err; | 1879 | return err; |
1880 | } | 1880 | } |
1881 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, | 1881 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, |
1882 | &p->sel, ctx, 0, &err); | 1882 | &p->sel, ctx, 0, &err); |
1883 | security_xfrm_policy_free(ctx); | 1883 | security_xfrm_policy_free(ctx); |
1884 | } | 1884 | } |
1885 | if (xp == NULL) | 1885 | if (xp == NULL) |
1886 | return -ENOENT; | 1886 | return -ENOENT; |
1887 | 1887 | ||
1888 | if (unlikely(xp->walk.dead)) | 1888 | if (unlikely(xp->walk.dead)) |
1889 | goto out; | 1889 | goto out; |
1890 | 1890 | ||
1891 | err = 0; | 1891 | err = 0; |
1892 | if (up->hard) { | 1892 | if (up->hard) { |
1893 | uid_t loginuid = audit_get_loginuid(current); | 1893 | uid_t loginuid = audit_get_loginuid(current); |
1894 | u32 sessionid = audit_get_sessionid(current); | 1894 | u32 sessionid = audit_get_sessionid(current); |
1895 | u32 sid; | 1895 | u32 sid; |
1896 | 1896 | ||
1897 | security_task_getsecid(current, &sid); | 1897 | security_task_getsecid(current, &sid); |
1898 | xfrm_policy_delete(xp, p->dir); | 1898 | xfrm_policy_delete(xp, p->dir); |
1899 | xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid); | 1899 | xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid); |
1900 | 1900 | ||
1901 | } else { | 1901 | } else { |
1902 | // reset the timers here? | 1902 | // reset the timers here? |
1903 | WARN(1, "Dont know what to do with soft policy expire\n"); | 1903 | WARN(1, "Dont know what to do with soft policy expire\n"); |
1904 | } | 1904 | } |
1905 | km_policy_expired(xp, p->dir, up->hard, current->pid); | 1905 | km_policy_expired(xp, p->dir, up->hard, current->pid); |
1906 | 1906 | ||
1907 | out: | 1907 | out: |
1908 | xfrm_pol_put(xp); | 1908 | xfrm_pol_put(xp); |
1909 | return err; | 1909 | return err; |
1910 | } | 1910 | } |
1911 | 1911 | ||
1912 | static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1912 | static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1913 | struct nlattr **attrs) | 1913 | struct nlattr **attrs) |
1914 | { | 1914 | { |
1915 | struct net *net = sock_net(skb->sk); | 1915 | struct net *net = sock_net(skb->sk); |
1916 | struct xfrm_state *x; | 1916 | struct xfrm_state *x; |
1917 | int err; | 1917 | int err; |
1918 | struct xfrm_user_expire *ue = nlmsg_data(nlh); | 1918 | struct xfrm_user_expire *ue = nlmsg_data(nlh); |
1919 | struct xfrm_usersa_info *p = &ue->state; | 1919 | struct xfrm_usersa_info *p = &ue->state; |
1920 | struct xfrm_mark m; | 1920 | struct xfrm_mark m; |
1921 | u32 mark = xfrm_mark_get(attrs, &m); | 1921 | u32 mark = xfrm_mark_get(attrs, &m); |
1922 | 1922 | ||
1923 | x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); | 1923 | x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); |
1924 | 1924 | ||
1925 | err = -ENOENT; | 1925 | err = -ENOENT; |
1926 | if (x == NULL) | 1926 | if (x == NULL) |
1927 | return err; | 1927 | return err; |
1928 | 1928 | ||
1929 | spin_lock_bh(&x->lock); | 1929 | spin_lock_bh(&x->lock); |
1930 | err = -EINVAL; | 1930 | err = -EINVAL; |
1931 | if (x->km.state != XFRM_STATE_VALID) | 1931 | if (x->km.state != XFRM_STATE_VALID) |
1932 | goto out; | 1932 | goto out; |
1933 | km_state_expired(x, ue->hard, current->pid); | 1933 | km_state_expired(x, ue->hard, current->pid); |
1934 | 1934 | ||
1935 | if (ue->hard) { | 1935 | if (ue->hard) { |
1936 | uid_t loginuid = audit_get_loginuid(current); | 1936 | uid_t loginuid = audit_get_loginuid(current); |
1937 | u32 sessionid = audit_get_sessionid(current); | 1937 | u32 sessionid = audit_get_sessionid(current); |
1938 | u32 sid; | 1938 | u32 sid; |
1939 | 1939 | ||
1940 | security_task_getsecid(current, &sid); | 1940 | security_task_getsecid(current, &sid); |
1941 | __xfrm_state_delete(x); | 1941 | __xfrm_state_delete(x); |
1942 | xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid); | 1942 | xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid); |
1943 | } | 1943 | } |
1944 | err = 0; | 1944 | err = 0; |
1945 | out: | 1945 | out: |
1946 | spin_unlock_bh(&x->lock); | 1946 | spin_unlock_bh(&x->lock); |
1947 | xfrm_state_put(x); | 1947 | xfrm_state_put(x); |
1948 | return err; | 1948 | return err; |
1949 | } | 1949 | } |
1950 | 1950 | ||
1951 | static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1951 | static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1952 | struct nlattr **attrs) | 1952 | struct nlattr **attrs) |
1953 | { | 1953 | { |
1954 | struct net *net = sock_net(skb->sk); | 1954 | struct net *net = sock_net(skb->sk); |
1955 | struct xfrm_policy *xp; | 1955 | struct xfrm_policy *xp; |
1956 | struct xfrm_user_tmpl *ut; | 1956 | struct xfrm_user_tmpl *ut; |
1957 | int i; | 1957 | int i; |
1958 | struct nlattr *rt = attrs[XFRMA_TMPL]; | 1958 | struct nlattr *rt = attrs[XFRMA_TMPL]; |
1959 | struct xfrm_mark mark; | 1959 | struct xfrm_mark mark; |
1960 | 1960 | ||
1961 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); | 1961 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); |
1962 | struct xfrm_state *x = xfrm_state_alloc(net); | 1962 | struct xfrm_state *x = xfrm_state_alloc(net); |
1963 | int err = -ENOMEM; | 1963 | int err = -ENOMEM; |
1964 | 1964 | ||
1965 | if (!x) | 1965 | if (!x) |
1966 | goto nomem; | 1966 | goto nomem; |
1967 | 1967 | ||
1968 | xfrm_mark_get(attrs, &mark); | 1968 | xfrm_mark_get(attrs, &mark); |
1969 | 1969 | ||
1970 | err = verify_newpolicy_info(&ua->policy); | 1970 | err = verify_newpolicy_info(&ua->policy); |
1971 | if (err) | 1971 | if (err) |
1972 | goto bad_policy; | 1972 | goto bad_policy; |
1973 | 1973 | ||
1974 | /* build an XP */ | 1974 | /* build an XP */ |
1975 | xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); | 1975 | xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); |
1976 | if (!xp) | 1976 | if (!xp) |
1977 | goto free_state; | 1977 | goto free_state; |
1978 | 1978 | ||
1979 | memcpy(&x->id, &ua->id, sizeof(ua->id)); | 1979 | memcpy(&x->id, &ua->id, sizeof(ua->id)); |
1980 | memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); | 1980 | memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); |
1981 | memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); | 1981 | memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); |
1982 | xp->mark.m = x->mark.m = mark.m; | 1982 | xp->mark.m = x->mark.m = mark.m; |
1983 | xp->mark.v = x->mark.v = mark.v; | 1983 | xp->mark.v = x->mark.v = mark.v; |
1984 | ut = nla_data(rt); | 1984 | ut = nla_data(rt); |
1985 | /* extract the templates and for each call km_key */ | 1985 | /* extract the templates and for each call km_key */ |
1986 | for (i = 0; i < xp->xfrm_nr; i++, ut++) { | 1986 | for (i = 0; i < xp->xfrm_nr; i++, ut++) { |
1987 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; | 1987 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; |
1988 | memcpy(&x->id, &t->id, sizeof(x->id)); | 1988 | memcpy(&x->id, &t->id, sizeof(x->id)); |
1989 | x->props.mode = t->mode; | 1989 | x->props.mode = t->mode; |
1990 | x->props.reqid = t->reqid; | 1990 | x->props.reqid = t->reqid; |
1991 | x->props.family = ut->family; | 1991 | x->props.family = ut->family; |
1992 | t->aalgos = ua->aalgos; | 1992 | t->aalgos = ua->aalgos; |
1993 | t->ealgos = ua->ealgos; | 1993 | t->ealgos = ua->ealgos; |
1994 | t->calgos = ua->calgos; | 1994 | t->calgos = ua->calgos; |
1995 | err = km_query(x, t, xp); | 1995 | err = km_query(x, t, xp); |
1996 | 1996 | ||
1997 | } | 1997 | } |
1998 | 1998 | ||
1999 | kfree(x); | 1999 | kfree(x); |
2000 | kfree(xp); | 2000 | kfree(xp); |
2001 | 2001 | ||
2002 | return 0; | 2002 | return 0; |
2003 | 2003 | ||
2004 | bad_policy: | 2004 | bad_policy: |
2005 | WARN(1, "BAD policy passed\n"); | 2005 | WARN(1, "BAD policy passed\n"); |
2006 | free_state: | 2006 | free_state: |
2007 | kfree(x); | 2007 | kfree(x); |
2008 | nomem: | 2008 | nomem: |
2009 | return err; | 2009 | return err; |
2010 | } | 2010 | } |
2011 | 2011 | ||
2012 | #ifdef CONFIG_XFRM_MIGRATE | 2012 | #ifdef CONFIG_XFRM_MIGRATE |
2013 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 2013 | static int copy_from_user_migrate(struct xfrm_migrate *ma, |
2014 | struct xfrm_kmaddress *k, | 2014 | struct xfrm_kmaddress *k, |
2015 | struct nlattr **attrs, int *num) | 2015 | struct nlattr **attrs, int *num) |
2016 | { | 2016 | { |
2017 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; | 2017 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
2018 | struct xfrm_user_migrate *um; | 2018 | struct xfrm_user_migrate *um; |
2019 | int i, num_migrate; | 2019 | int i, num_migrate; |
2020 | 2020 | ||
2021 | if (k != NULL) { | 2021 | if (k != NULL) { |
2022 | struct xfrm_user_kmaddress *uk; | 2022 | struct xfrm_user_kmaddress *uk; |
2023 | 2023 | ||
2024 | uk = nla_data(attrs[XFRMA_KMADDRESS]); | 2024 | uk = nla_data(attrs[XFRMA_KMADDRESS]); |
2025 | memcpy(&k->local, &uk->local, sizeof(k->local)); | 2025 | memcpy(&k->local, &uk->local, sizeof(k->local)); |
2026 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); | 2026 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); |
2027 | k->family = uk->family; | 2027 | k->family = uk->family; |
2028 | k->reserved = uk->reserved; | 2028 | k->reserved = uk->reserved; |
2029 | } | 2029 | } |
2030 | 2030 | ||
2031 | um = nla_data(rt); | 2031 | um = nla_data(rt); |
2032 | num_migrate = nla_len(rt) / sizeof(*um); | 2032 | num_migrate = nla_len(rt) / sizeof(*um); |
2033 | 2033 | ||
2034 | if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH) | 2034 | if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH) |
2035 | return -EINVAL; | 2035 | return -EINVAL; |
2036 | 2036 | ||
2037 | for (i = 0; i < num_migrate; i++, um++, ma++) { | 2037 | for (i = 0; i < num_migrate; i++, um++, ma++) { |
2038 | memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr)); | 2038 | memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr)); |
2039 | memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr)); | 2039 | memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr)); |
2040 | memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr)); | 2040 | memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr)); |
2041 | memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr)); | 2041 | memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr)); |
2042 | 2042 | ||
2043 | ma->proto = um->proto; | 2043 | ma->proto = um->proto; |
2044 | ma->mode = um->mode; | 2044 | ma->mode = um->mode; |
2045 | ma->reqid = um->reqid; | 2045 | ma->reqid = um->reqid; |
2046 | 2046 | ||
2047 | ma->old_family = um->old_family; | 2047 | ma->old_family = um->old_family; |
2048 | ma->new_family = um->new_family; | 2048 | ma->new_family = um->new_family; |
2049 | } | 2049 | } |
2050 | 2050 | ||
2051 | *num = i; | 2051 | *num = i; |
2052 | return 0; | 2052 | return 0; |
2053 | } | 2053 | } |
2054 | 2054 | ||
2055 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | 2055 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, |
2056 | struct nlattr **attrs) | 2056 | struct nlattr **attrs) |
2057 | { | 2057 | { |
2058 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); | 2058 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
2059 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 2059 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
2060 | struct xfrm_kmaddress km, *kmp; | 2060 | struct xfrm_kmaddress km, *kmp; |
2061 | u8 type; | 2061 | u8 type; |
2062 | int err; | 2062 | int err; |
2063 | int n = 0; | 2063 | int n = 0; |
2064 | 2064 | ||
2065 | if (attrs[XFRMA_MIGRATE] == NULL) | 2065 | if (attrs[XFRMA_MIGRATE] == NULL) |
2066 | return -EINVAL; | 2066 | return -EINVAL; |
2067 | 2067 | ||
2068 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; | 2068 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; |
2069 | 2069 | ||
2070 | err = copy_from_user_policy_type(&type, attrs); | 2070 | err = copy_from_user_policy_type(&type, attrs); |
2071 | if (err) | 2071 | if (err) |
2072 | return err; | 2072 | return err; |
2073 | 2073 | ||
2074 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); | 2074 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
2075 | if (err) | 2075 | if (err) |
2076 | return err; | 2076 | return err; |
2077 | 2077 | ||
2078 | if (!n) | 2078 | if (!n) |
2079 | return 0; | 2079 | return 0; |
2080 | 2080 | ||
2081 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); | 2081 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
2082 | 2082 | ||
2083 | return 0; | 2083 | return 0; |
2084 | } | 2084 | } |
2085 | #else | 2085 | #else |
2086 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | 2086 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, |
2087 | struct nlattr **attrs) | 2087 | struct nlattr **attrs) |
2088 | { | 2088 | { |
2089 | return -ENOPROTOOPT; | 2089 | return -ENOPROTOOPT; |
2090 | } | 2090 | } |
2091 | #endif | 2091 | #endif |
2092 | 2092 | ||
2093 | #ifdef CONFIG_XFRM_MIGRATE | 2093 | #ifdef CONFIG_XFRM_MIGRATE |
2094 | static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb) | 2094 | static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb) |
2095 | { | 2095 | { |
2096 | struct xfrm_user_migrate um; | 2096 | struct xfrm_user_migrate um; |
2097 | 2097 | ||
2098 | memset(&um, 0, sizeof(um)); | 2098 | memset(&um, 0, sizeof(um)); |
2099 | um.proto = m->proto; | 2099 | um.proto = m->proto; |
2100 | um.mode = m->mode; | 2100 | um.mode = m->mode; |
2101 | um.reqid = m->reqid; | 2101 | um.reqid = m->reqid; |
2102 | um.old_family = m->old_family; | 2102 | um.old_family = m->old_family; |
2103 | memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr)); | 2103 | memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr)); |
2104 | memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr)); | 2104 | memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr)); |
2105 | um.new_family = m->new_family; | 2105 | um.new_family = m->new_family; |
2106 | memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr)); | 2106 | memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr)); |
2107 | memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr)); | 2107 | memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr)); |
2108 | 2108 | ||
2109 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 2109 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
2110 | } | 2110 | } |
2111 | 2111 | ||
2112 | static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb) | 2112 | static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb) |
2113 | { | 2113 | { |
2114 | struct xfrm_user_kmaddress uk; | 2114 | struct xfrm_user_kmaddress uk; |
2115 | 2115 | ||
2116 | memset(&uk, 0, sizeof(uk)); | 2116 | memset(&uk, 0, sizeof(uk)); |
2117 | uk.family = k->family; | 2117 | uk.family = k->family; |
2118 | uk.reserved = k->reserved; | 2118 | uk.reserved = k->reserved; |
2119 | memcpy(&uk.local, &k->local, sizeof(uk.local)); | 2119 | memcpy(&uk.local, &k->local, sizeof(uk.local)); |
2120 | memcpy(&uk.remote, &k->remote, sizeof(uk.remote)); | 2120 | memcpy(&uk.remote, &k->remote, sizeof(uk.remote)); |
2121 | 2121 | ||
2122 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | 2122 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); |
2123 | } | 2123 | } |
2124 | 2124 | ||
2125 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | 2125 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) |
2126 | { | 2126 | { |
2127 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 2127 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
2128 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) | 2128 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
2129 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 2129 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
2130 | + userpolicy_type_attrsize(); | 2130 | + userpolicy_type_attrsize(); |
2131 | } | 2131 | } |
2132 | 2132 | ||
2133 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, | 2133 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, |
2134 | int num_migrate, const struct xfrm_kmaddress *k, | 2134 | int num_migrate, const struct xfrm_kmaddress *k, |
2135 | const struct xfrm_selector *sel, u8 dir, u8 type) | 2135 | const struct xfrm_selector *sel, u8 dir, u8 type) |
2136 | { | 2136 | { |
2137 | const struct xfrm_migrate *mp; | 2137 | const struct xfrm_migrate *mp; |
2138 | struct xfrm_userpolicy_id *pol_id; | 2138 | struct xfrm_userpolicy_id *pol_id; |
2139 | struct nlmsghdr *nlh; | 2139 | struct nlmsghdr *nlh; |
2140 | int i; | 2140 | int i; |
2141 | 2141 | ||
2142 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0); | 2142 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0); |
2143 | if (nlh == NULL) | 2143 | if (nlh == NULL) |
2144 | return -EMSGSIZE; | 2144 | return -EMSGSIZE; |
2145 | 2145 | ||
2146 | pol_id = nlmsg_data(nlh); | 2146 | pol_id = nlmsg_data(nlh); |
2147 | /* copy data from selector, dir, and type to the pol_id */ | 2147 | /* copy data from selector, dir, and type to the pol_id */ |
2148 | memset(pol_id, 0, sizeof(*pol_id)); | 2148 | memset(pol_id, 0, sizeof(*pol_id)); |
2149 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | 2149 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); |
2150 | pol_id->dir = dir; | 2150 | pol_id->dir = dir; |
2151 | 2151 | ||
2152 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) | 2152 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) |
2153 | goto nlmsg_failure; | 2153 | goto nlmsg_failure; |
2154 | 2154 | ||
2155 | if (copy_to_user_policy_type(type, skb) < 0) | 2155 | if (copy_to_user_policy_type(type, skb) < 0) |
2156 | goto nlmsg_failure; | 2156 | goto nlmsg_failure; |
2157 | 2157 | ||
2158 | for (i = 0, mp = m ; i < num_migrate; i++, mp++) { | 2158 | for (i = 0, mp = m ; i < num_migrate; i++, mp++) { |
2159 | if (copy_to_user_migrate(mp, skb) < 0) | 2159 | if (copy_to_user_migrate(mp, skb) < 0) |
2160 | goto nlmsg_failure; | 2160 | goto nlmsg_failure; |
2161 | } | 2161 | } |
2162 | 2162 | ||
2163 | return nlmsg_end(skb, nlh); | 2163 | return nlmsg_end(skb, nlh); |
2164 | nlmsg_failure: | 2164 | nlmsg_failure: |
2165 | nlmsg_cancel(skb, nlh); | 2165 | nlmsg_cancel(skb, nlh); |
2166 | return -EMSGSIZE; | 2166 | return -EMSGSIZE; |
2167 | } | 2167 | } |
2168 | 2168 | ||
2169 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2169 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2170 | const struct xfrm_migrate *m, int num_migrate, | 2170 | const struct xfrm_migrate *m, int num_migrate, |
2171 | const struct xfrm_kmaddress *k) | 2171 | const struct xfrm_kmaddress *k) |
2172 | { | 2172 | { |
2173 | struct net *net = &init_net; | 2173 | struct net *net = &init_net; |
2174 | struct sk_buff *skb; | 2174 | struct sk_buff *skb; |
2175 | 2175 | ||
2176 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); | 2176 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
2177 | if (skb == NULL) | 2177 | if (skb == NULL) |
2178 | return -ENOMEM; | 2178 | return -ENOMEM; |
2179 | 2179 | ||
2180 | /* build migrate */ | 2180 | /* build migrate */ |
2181 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) | 2181 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
2182 | BUG(); | 2182 | BUG(); |
2183 | 2183 | ||
2184 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 2184 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
2185 | } | 2185 | } |
2186 | #else | 2186 | #else |
2187 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2187 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2188 | const struct xfrm_migrate *m, int num_migrate, | 2188 | const struct xfrm_migrate *m, int num_migrate, |
2189 | const struct xfrm_kmaddress *k) | 2189 | const struct xfrm_kmaddress *k) |
2190 | { | 2190 | { |
2191 | return -ENOPROTOOPT; | 2191 | return -ENOPROTOOPT; |
2192 | } | 2192 | } |
2193 | #endif | 2193 | #endif |
2194 | 2194 | ||
2195 | #define XMSGSIZE(type) sizeof(struct type) | 2195 | #define XMSGSIZE(type) sizeof(struct type) |
2196 | 2196 | ||
2197 | static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | 2197 | static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { |
2198 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), | 2198 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), |
2199 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), | 2199 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), |
2200 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), | 2200 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), |
2201 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), | 2201 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), |
2202 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 2202 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
2203 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 2203 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
2204 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), | 2204 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), |
2205 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), | 2205 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), |
2206 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), | 2206 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), |
2207 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), | 2207 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), |
2208 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), | 2208 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), |
2209 | [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), | 2209 | [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), |
2210 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), | 2210 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), |
2211 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0, | 2211 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0, |
2212 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | 2212 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), |
2213 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | 2213 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), |
2214 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), | 2214 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), |
2215 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 2215 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
2216 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), | 2216 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), |
2217 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), | 2217 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), |
2218 | }; | 2218 | }; |
2219 | 2219 | ||
2220 | #undef XMSGSIZE | 2220 | #undef XMSGSIZE |
2221 | 2221 | ||
2222 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | 2222 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { |
2223 | [XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, | 2223 | [XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, |
2224 | [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, | 2224 | [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, |
2225 | [XFRMA_LASTUSED] = { .type = NLA_U64}, | 2225 | [XFRMA_LASTUSED] = { .type = NLA_U64}, |
2226 | [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, | 2226 | [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, |
2227 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, | 2227 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, |
2228 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, | 2228 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, |
2229 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, | 2229 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, |
2230 | [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, | 2230 | [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, |
2231 | [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) }, | 2231 | [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) }, |
2232 | [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) }, | 2232 | [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) }, |
2233 | [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) }, | 2233 | [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) }, |
2234 | [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) }, | 2234 | [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) }, |
2235 | [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) }, | 2235 | [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) }, |
2236 | [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, | 2236 | [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, |
2237 | [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 }, | 2237 | [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 }, |
2238 | [XFRMA_SRCADDR] = { .len = sizeof(xfrm_address_t) }, | 2238 | [XFRMA_SRCADDR] = { .len = sizeof(xfrm_address_t) }, |
2239 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, | 2239 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, |
2240 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 2240 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
2241 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 2241 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
2242 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | 2242 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, |
2243 | [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, | 2243 | [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, |
2244 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, | 2244 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, |
2245 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, | 2245 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, |
2246 | }; | 2246 | }; |
2247 | 2247 | ||
2248 | static struct xfrm_link { | 2248 | static struct xfrm_link { |
2249 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); | 2249 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); |
2250 | int (*dump)(struct sk_buff *, struct netlink_callback *); | 2250 | int (*dump)(struct sk_buff *, struct netlink_callback *); |
2251 | int (*done)(struct netlink_callback *); | 2251 | int (*done)(struct netlink_callback *); |
2252 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { | 2252 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { |
2253 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, | 2253 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
2254 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, | 2254 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, |
2255 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa, | 2255 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa, |
2256 | .dump = xfrm_dump_sa, | 2256 | .dump = xfrm_dump_sa, |
2257 | .done = xfrm_dump_sa_done }, | 2257 | .done = xfrm_dump_sa_done }, |
2258 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, | 2258 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, |
2259 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, | 2259 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, |
2260 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, | 2260 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, |
2261 | .dump = xfrm_dump_policy, | 2261 | .dump = xfrm_dump_policy, |
2262 | .done = xfrm_dump_policy_done }, | 2262 | .done = xfrm_dump_policy_done }, |
2263 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, | 2263 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, |
2264 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, | 2264 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, |
2265 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, | 2265 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, |
2266 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, | 2266 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, |
2267 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, | 2267 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
2268 | [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire}, | 2268 | [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire}, |
2269 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, | 2269 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, |
2270 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, | 2270 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, |
2271 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, | 2271 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, |
2272 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, | 2272 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, |
2273 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, | 2273 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, |
2274 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, | 2274 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, |
2275 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, | 2275 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, |
2276 | }; | 2276 | }; |
2277 | 2277 | ||
2278 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 2278 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
2279 | { | 2279 | { |
2280 | struct net *net = sock_net(skb->sk); | 2280 | struct net *net = sock_net(skb->sk); |
2281 | struct nlattr *attrs[XFRMA_MAX+1]; | 2281 | struct nlattr *attrs[XFRMA_MAX+1]; |
2282 | struct xfrm_link *link; | 2282 | struct xfrm_link *link; |
2283 | int type, err; | 2283 | int type, err; |
2284 | 2284 | ||
2285 | type = nlh->nlmsg_type; | 2285 | type = nlh->nlmsg_type; |
2286 | if (type > XFRM_MSG_MAX) | 2286 | if (type > XFRM_MSG_MAX) |
2287 | return -EINVAL; | 2287 | return -EINVAL; |
2288 | 2288 | ||
2289 | type -= XFRM_MSG_BASE; | 2289 | type -= XFRM_MSG_BASE; |
2290 | link = &xfrm_dispatch[type]; | 2290 | link = &xfrm_dispatch[type]; |
2291 | 2291 | ||
2292 | /* All operations require privileges, even GET */ | 2292 | /* All operations require privileges, even GET */ |
2293 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 2293 | if (!capable(CAP_NET_ADMIN)) |
2294 | return -EPERM; | 2294 | return -EPERM; |
2295 | 2295 | ||
2296 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || | 2296 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || |
2297 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && | 2297 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && |
2298 | (nlh->nlmsg_flags & NLM_F_DUMP)) { | 2298 | (nlh->nlmsg_flags & NLM_F_DUMP)) { |
2299 | if (link->dump == NULL) | 2299 | if (link->dump == NULL) |
2300 | return -EINVAL; | 2300 | return -EINVAL; |
2301 | 2301 | ||
2302 | return netlink_dump_start(net->xfrm.nlsk, skb, nlh, | 2302 | return netlink_dump_start(net->xfrm.nlsk, skb, nlh, |
2303 | link->dump, link->done, 0); | 2303 | link->dump, link->done, 0); |
2304 | } | 2304 | } |
2305 | 2305 | ||
2306 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, | 2306 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, |
2307 | xfrma_policy); | 2307 | xfrma_policy); |
2308 | if (err < 0) | 2308 | if (err < 0) |
2309 | return err; | 2309 | return err; |
2310 | 2310 | ||
2311 | if (link->doit == NULL) | 2311 | if (link->doit == NULL) |
2312 | return -EINVAL; | 2312 | return -EINVAL; |
2313 | 2313 | ||
2314 | return link->doit(skb, nlh, attrs); | 2314 | return link->doit(skb, nlh, attrs); |
2315 | } | 2315 | } |
2316 | 2316 | ||
2317 | static void xfrm_netlink_rcv(struct sk_buff *skb) | 2317 | static void xfrm_netlink_rcv(struct sk_buff *skb) |
2318 | { | 2318 | { |
2319 | mutex_lock(&xfrm_cfg_mutex); | 2319 | mutex_lock(&xfrm_cfg_mutex); |
2320 | netlink_rcv_skb(skb, &xfrm_user_rcv_msg); | 2320 | netlink_rcv_skb(skb, &xfrm_user_rcv_msg); |
2321 | mutex_unlock(&xfrm_cfg_mutex); | 2321 | mutex_unlock(&xfrm_cfg_mutex); |
2322 | } | 2322 | } |
2323 | 2323 | ||
2324 | static inline size_t xfrm_expire_msgsize(void) | 2324 | static inline size_t xfrm_expire_msgsize(void) |
2325 | { | 2325 | { |
2326 | return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) | 2326 | return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) |
2327 | + nla_total_size(sizeof(struct xfrm_mark)); | 2327 | + nla_total_size(sizeof(struct xfrm_mark)); |
2328 | } | 2328 | } |
2329 | 2329 | ||
2330 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) | 2330 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
2331 | { | 2331 | { |
2332 | struct xfrm_user_expire *ue; | 2332 | struct xfrm_user_expire *ue; |
2333 | struct nlmsghdr *nlh; | 2333 | struct nlmsghdr *nlh; |
2334 | 2334 | ||
2335 | nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0); | 2335 | nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0); |
2336 | if (nlh == NULL) | 2336 | if (nlh == NULL) |
2337 | return -EMSGSIZE; | 2337 | return -EMSGSIZE; |
2338 | 2338 | ||
2339 | ue = nlmsg_data(nlh); | 2339 | ue = nlmsg_data(nlh); |
2340 | copy_to_user_state(x, &ue->state); | 2340 | copy_to_user_state(x, &ue->state); |
2341 | ue->hard = (c->data.hard != 0) ? 1 : 0; | 2341 | ue->hard = (c->data.hard != 0) ? 1 : 0; |
2342 | 2342 | ||
2343 | if (xfrm_mark_put(skb, &x->mark)) | 2343 | if (xfrm_mark_put(skb, &x->mark)) |
2344 | goto nla_put_failure; | 2344 | goto nla_put_failure; |
2345 | 2345 | ||
2346 | return nlmsg_end(skb, nlh); | 2346 | return nlmsg_end(skb, nlh); |
2347 | 2347 | ||
2348 | nla_put_failure: | 2348 | nla_put_failure: |
2349 | return -EMSGSIZE; | 2349 | return -EMSGSIZE; |
2350 | } | 2350 | } |
2351 | 2351 | ||
2352 | static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c) | 2352 | static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c) |
2353 | { | 2353 | { |
2354 | struct net *net = xs_net(x); | 2354 | struct net *net = xs_net(x); |
2355 | struct sk_buff *skb; | 2355 | struct sk_buff *skb; |
2356 | 2356 | ||
2357 | skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); | 2357 | skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); |
2358 | if (skb == NULL) | 2358 | if (skb == NULL) |
2359 | return -ENOMEM; | 2359 | return -ENOMEM; |
2360 | 2360 | ||
2361 | if (build_expire(skb, x, c) < 0) { | 2361 | if (build_expire(skb, x, c) < 0) { |
2362 | kfree_skb(skb); | 2362 | kfree_skb(skb); |
2363 | return -EMSGSIZE; | 2363 | return -EMSGSIZE; |
2364 | } | 2364 | } |
2365 | 2365 | ||
2366 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2366 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2367 | } | 2367 | } |
2368 | 2368 | ||
2369 | static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c) | 2369 | static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c) |
2370 | { | 2370 | { |
2371 | struct net *net = xs_net(x); | 2371 | struct net *net = xs_net(x); |
2372 | struct sk_buff *skb; | 2372 | struct sk_buff *skb; |
2373 | 2373 | ||
2374 | skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); | 2374 | skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); |
2375 | if (skb == NULL) | 2375 | if (skb == NULL) |
2376 | return -ENOMEM; | 2376 | return -ENOMEM; |
2377 | 2377 | ||
2378 | if (build_aevent(skb, x, c) < 0) | 2378 | if (build_aevent(skb, x, c) < 0) |
2379 | BUG(); | 2379 | BUG(); |
2380 | 2380 | ||
2381 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); | 2381 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); |
2382 | } | 2382 | } |
2383 | 2383 | ||
2384 | static int xfrm_notify_sa_flush(const struct km_event *c) | 2384 | static int xfrm_notify_sa_flush(const struct km_event *c) |
2385 | { | 2385 | { |
2386 | struct net *net = c->net; | 2386 | struct net *net = c->net; |
2387 | struct xfrm_usersa_flush *p; | 2387 | struct xfrm_usersa_flush *p; |
2388 | struct nlmsghdr *nlh; | 2388 | struct nlmsghdr *nlh; |
2389 | struct sk_buff *skb; | 2389 | struct sk_buff *skb; |
2390 | int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush)); | 2390 | int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush)); |
2391 | 2391 | ||
2392 | skb = nlmsg_new(len, GFP_ATOMIC); | 2392 | skb = nlmsg_new(len, GFP_ATOMIC); |
2393 | if (skb == NULL) | 2393 | if (skb == NULL) |
2394 | return -ENOMEM; | 2394 | return -ENOMEM; |
2395 | 2395 | ||
2396 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0); | 2396 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0); |
2397 | if (nlh == NULL) { | 2397 | if (nlh == NULL) { |
2398 | kfree_skb(skb); | 2398 | kfree_skb(skb); |
2399 | return -EMSGSIZE; | 2399 | return -EMSGSIZE; |
2400 | } | 2400 | } |
2401 | 2401 | ||
2402 | p = nlmsg_data(nlh); | 2402 | p = nlmsg_data(nlh); |
2403 | p->proto = c->data.proto; | 2403 | p->proto = c->data.proto; |
2404 | 2404 | ||
2405 | nlmsg_end(skb, nlh); | 2405 | nlmsg_end(skb, nlh); |
2406 | 2406 | ||
2407 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); | 2407 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
2408 | } | 2408 | } |
2409 | 2409 | ||
2410 | static inline size_t xfrm_sa_len(struct xfrm_state *x) | 2410 | static inline size_t xfrm_sa_len(struct xfrm_state *x) |
2411 | { | 2411 | { |
2412 | size_t l = 0; | 2412 | size_t l = 0; |
2413 | if (x->aead) | 2413 | if (x->aead) |
2414 | l += nla_total_size(aead_len(x->aead)); | 2414 | l += nla_total_size(aead_len(x->aead)); |
2415 | if (x->aalg) { | 2415 | if (x->aalg) { |
2416 | l += nla_total_size(sizeof(struct xfrm_algo) + | 2416 | l += nla_total_size(sizeof(struct xfrm_algo) + |
2417 | (x->aalg->alg_key_len + 7) / 8); | 2417 | (x->aalg->alg_key_len + 7) / 8); |
2418 | l += nla_total_size(xfrm_alg_auth_len(x->aalg)); | 2418 | l += nla_total_size(xfrm_alg_auth_len(x->aalg)); |
2419 | } | 2419 | } |
2420 | if (x->ealg) | 2420 | if (x->ealg) |
2421 | l += nla_total_size(xfrm_alg_len(x->ealg)); | 2421 | l += nla_total_size(xfrm_alg_len(x->ealg)); |
2422 | if (x->calg) | 2422 | if (x->calg) |
2423 | l += nla_total_size(sizeof(*x->calg)); | 2423 | l += nla_total_size(sizeof(*x->calg)); |
2424 | if (x->encap) | 2424 | if (x->encap) |
2425 | l += nla_total_size(sizeof(*x->encap)); | 2425 | l += nla_total_size(sizeof(*x->encap)); |
2426 | if (x->tfcpad) | 2426 | if (x->tfcpad) |
2427 | l += nla_total_size(sizeof(x->tfcpad)); | 2427 | l += nla_total_size(sizeof(x->tfcpad)); |
2428 | if (x->replay_esn) | 2428 | if (x->replay_esn) |
2429 | l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn)); | 2429 | l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn)); |
2430 | if (x->security) | 2430 | if (x->security) |
2431 | l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + | 2431 | l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + |
2432 | x->security->ctx_len); | 2432 | x->security->ctx_len); |
2433 | if (x->coaddr) | 2433 | if (x->coaddr) |
2434 | l += nla_total_size(sizeof(*x->coaddr)); | 2434 | l += nla_total_size(sizeof(*x->coaddr)); |
2435 | 2435 | ||
2436 | /* Must count x->lastused as it may become non-zero behind our back. */ | 2436 | /* Must count x->lastused as it may become non-zero behind our back. */ |
2437 | l += nla_total_size(sizeof(u64)); | 2437 | l += nla_total_size(sizeof(u64)); |
2438 | 2438 | ||
2439 | return l; | 2439 | return l; |
2440 | } | 2440 | } |
2441 | 2441 | ||
2442 | static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c) | 2442 | static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c) |
2443 | { | 2443 | { |
2444 | struct net *net = xs_net(x); | 2444 | struct net *net = xs_net(x); |
2445 | struct xfrm_usersa_info *p; | 2445 | struct xfrm_usersa_info *p; |
2446 | struct xfrm_usersa_id *id; | 2446 | struct xfrm_usersa_id *id; |
2447 | struct nlmsghdr *nlh; | 2447 | struct nlmsghdr *nlh; |
2448 | struct sk_buff *skb; | 2448 | struct sk_buff *skb; |
2449 | int len = xfrm_sa_len(x); | 2449 | int len = xfrm_sa_len(x); |
2450 | int headlen; | 2450 | int headlen; |
2451 | 2451 | ||
2452 | headlen = sizeof(*p); | 2452 | headlen = sizeof(*p); |
2453 | if (c->event == XFRM_MSG_DELSA) { | 2453 | if (c->event == XFRM_MSG_DELSA) { |
2454 | len += nla_total_size(headlen); | 2454 | len += nla_total_size(headlen); |
2455 | headlen = sizeof(*id); | 2455 | headlen = sizeof(*id); |
2456 | len += nla_total_size(sizeof(struct xfrm_mark)); | 2456 | len += nla_total_size(sizeof(struct xfrm_mark)); |
2457 | } | 2457 | } |
2458 | len += NLMSG_ALIGN(headlen); | 2458 | len += NLMSG_ALIGN(headlen); |
2459 | 2459 | ||
2460 | skb = nlmsg_new(len, GFP_ATOMIC); | 2460 | skb = nlmsg_new(len, GFP_ATOMIC); |
2461 | if (skb == NULL) | 2461 | if (skb == NULL) |
2462 | return -ENOMEM; | 2462 | return -ENOMEM; |
2463 | 2463 | ||
2464 | nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); | 2464 | nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); |
2465 | if (nlh == NULL) | 2465 | if (nlh == NULL) |
2466 | goto nla_put_failure; | 2466 | goto nla_put_failure; |
2467 | 2467 | ||
2468 | p = nlmsg_data(nlh); | 2468 | p = nlmsg_data(nlh); |
2469 | if (c->event == XFRM_MSG_DELSA) { | 2469 | if (c->event == XFRM_MSG_DELSA) { |
2470 | struct nlattr *attr; | 2470 | struct nlattr *attr; |
2471 | 2471 | ||
2472 | id = nlmsg_data(nlh); | 2472 | id = nlmsg_data(nlh); |
2473 | memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr)); | 2473 | memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr)); |
2474 | id->spi = x->id.spi; | 2474 | id->spi = x->id.spi; |
2475 | id->family = x->props.family; | 2475 | id->family = x->props.family; |
2476 | id->proto = x->id.proto; | 2476 | id->proto = x->id.proto; |
2477 | 2477 | ||
2478 | attr = nla_reserve(skb, XFRMA_SA, sizeof(*p)); | 2478 | attr = nla_reserve(skb, XFRMA_SA, sizeof(*p)); |
2479 | if (attr == NULL) | 2479 | if (attr == NULL) |
2480 | goto nla_put_failure; | 2480 | goto nla_put_failure; |
2481 | 2481 | ||
2482 | p = nla_data(attr); | 2482 | p = nla_data(attr); |
2483 | } | 2483 | } |
2484 | 2484 | ||
2485 | if (copy_to_user_state_extra(x, p, skb)) | 2485 | if (copy_to_user_state_extra(x, p, skb)) |
2486 | goto nla_put_failure; | 2486 | goto nla_put_failure; |
2487 | 2487 | ||
2488 | nlmsg_end(skb, nlh); | 2488 | nlmsg_end(skb, nlh); |
2489 | 2489 | ||
2490 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); | 2490 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
2491 | 2491 | ||
2492 | nla_put_failure: | 2492 | nla_put_failure: |
2493 | /* Somebody screwed up with xfrm_sa_len! */ | 2493 | /* Somebody screwed up with xfrm_sa_len! */ |
2494 | WARN_ON(1); | 2494 | WARN_ON(1); |
2495 | kfree_skb(skb); | 2495 | kfree_skb(skb); |
2496 | return -1; | 2496 | return -1; |
2497 | } | 2497 | } |
2498 | 2498 | ||
2499 | static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c) | 2499 | static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c) |
2500 | { | 2500 | { |
2501 | 2501 | ||
2502 | switch (c->event) { | 2502 | switch (c->event) { |
2503 | case XFRM_MSG_EXPIRE: | 2503 | case XFRM_MSG_EXPIRE: |
2504 | return xfrm_exp_state_notify(x, c); | 2504 | return xfrm_exp_state_notify(x, c); |
2505 | case XFRM_MSG_NEWAE: | 2505 | case XFRM_MSG_NEWAE: |
2506 | return xfrm_aevent_state_notify(x, c); | 2506 | return xfrm_aevent_state_notify(x, c); |
2507 | case XFRM_MSG_DELSA: | 2507 | case XFRM_MSG_DELSA: |
2508 | case XFRM_MSG_UPDSA: | 2508 | case XFRM_MSG_UPDSA: |
2509 | case XFRM_MSG_NEWSA: | 2509 | case XFRM_MSG_NEWSA: |
2510 | return xfrm_notify_sa(x, c); | 2510 | return xfrm_notify_sa(x, c); |
2511 | case XFRM_MSG_FLUSHSA: | 2511 | case XFRM_MSG_FLUSHSA: |
2512 | return xfrm_notify_sa_flush(c); | 2512 | return xfrm_notify_sa_flush(c); |
2513 | default: | 2513 | default: |
2514 | printk(KERN_NOTICE "xfrm_user: Unknown SA event %d\n", | 2514 | printk(KERN_NOTICE "xfrm_user: Unknown SA event %d\n", |
2515 | c->event); | 2515 | c->event); |
2516 | break; | 2516 | break; |
2517 | } | 2517 | } |
2518 | 2518 | ||
2519 | return 0; | 2519 | return 0; |
2520 | 2520 | ||
2521 | } | 2521 | } |
2522 | 2522 | ||
2523 | static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, | 2523 | static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, |
2524 | struct xfrm_policy *xp) | 2524 | struct xfrm_policy *xp) |
2525 | { | 2525 | { |
2526 | return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) | 2526 | return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) |
2527 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) | 2527 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
2528 | + nla_total_size(sizeof(struct xfrm_mark)) | 2528 | + nla_total_size(sizeof(struct xfrm_mark)) |
2529 | + nla_total_size(xfrm_user_sec_ctx_size(x->security)) | 2529 | + nla_total_size(xfrm_user_sec_ctx_size(x->security)) |
2530 | + userpolicy_type_attrsize(); | 2530 | + userpolicy_type_attrsize(); |
2531 | } | 2531 | } |
2532 | 2532 | ||
2533 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | 2533 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, |
2534 | struct xfrm_tmpl *xt, struct xfrm_policy *xp, | 2534 | struct xfrm_tmpl *xt, struct xfrm_policy *xp, |
2535 | int dir) | 2535 | int dir) |
2536 | { | 2536 | { |
2537 | struct xfrm_user_acquire *ua; | 2537 | struct xfrm_user_acquire *ua; |
2538 | struct nlmsghdr *nlh; | 2538 | struct nlmsghdr *nlh; |
2539 | __u32 seq = xfrm_get_acqseq(); | 2539 | __u32 seq = xfrm_get_acqseq(); |
2540 | 2540 | ||
2541 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0); | 2541 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0); |
2542 | if (nlh == NULL) | 2542 | if (nlh == NULL) |
2543 | return -EMSGSIZE; | 2543 | return -EMSGSIZE; |
2544 | 2544 | ||
2545 | ua = nlmsg_data(nlh); | 2545 | ua = nlmsg_data(nlh); |
2546 | memcpy(&ua->id, &x->id, sizeof(ua->id)); | 2546 | memcpy(&ua->id, &x->id, sizeof(ua->id)); |
2547 | memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); | 2547 | memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); |
2548 | memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); | 2548 | memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); |
2549 | copy_to_user_policy(xp, &ua->policy, dir); | 2549 | copy_to_user_policy(xp, &ua->policy, dir); |
2550 | ua->aalgos = xt->aalgos; | 2550 | ua->aalgos = xt->aalgos; |
2551 | ua->ealgos = xt->ealgos; | 2551 | ua->ealgos = xt->ealgos; |
2552 | ua->calgos = xt->calgos; | 2552 | ua->calgos = xt->calgos; |
2553 | ua->seq = x->km.seq = seq; | 2553 | ua->seq = x->km.seq = seq; |
2554 | 2554 | ||
2555 | if (copy_to_user_tmpl(xp, skb) < 0) | 2555 | if (copy_to_user_tmpl(xp, skb) < 0) |
2556 | goto nlmsg_failure; | 2556 | goto nlmsg_failure; |
2557 | if (copy_to_user_state_sec_ctx(x, skb)) | 2557 | if (copy_to_user_state_sec_ctx(x, skb)) |
2558 | goto nlmsg_failure; | 2558 | goto nlmsg_failure; |
2559 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2559 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2560 | goto nlmsg_failure; | 2560 | goto nlmsg_failure; |
2561 | if (xfrm_mark_put(skb, &xp->mark)) | 2561 | if (xfrm_mark_put(skb, &xp->mark)) |
2562 | goto nla_put_failure; | 2562 | goto nla_put_failure; |
2563 | 2563 | ||
2564 | return nlmsg_end(skb, nlh); | 2564 | return nlmsg_end(skb, nlh); |
2565 | 2565 | ||
2566 | nla_put_failure: | 2566 | nla_put_failure: |
2567 | nlmsg_failure: | 2567 | nlmsg_failure: |
2568 | nlmsg_cancel(skb, nlh); | 2568 | nlmsg_cancel(skb, nlh); |
2569 | return -EMSGSIZE; | 2569 | return -EMSGSIZE; |
2570 | } | 2570 | } |
2571 | 2571 | ||
2572 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | 2572 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, |
2573 | struct xfrm_policy *xp, int dir) | 2573 | struct xfrm_policy *xp, int dir) |
2574 | { | 2574 | { |
2575 | struct net *net = xs_net(x); | 2575 | struct net *net = xs_net(x); |
2576 | struct sk_buff *skb; | 2576 | struct sk_buff *skb; |
2577 | 2577 | ||
2578 | skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); | 2578 | skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); |
2579 | if (skb == NULL) | 2579 | if (skb == NULL) |
2580 | return -ENOMEM; | 2580 | return -ENOMEM; |
2581 | 2581 | ||
2582 | if (build_acquire(skb, x, xt, xp, dir) < 0) | 2582 | if (build_acquire(skb, x, xt, xp, dir) < 0) |
2583 | BUG(); | 2583 | BUG(); |
2584 | 2584 | ||
2585 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); | 2585 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); |
2586 | } | 2586 | } |
2587 | 2587 | ||
2588 | /* User gives us xfrm_user_policy_info followed by an array of 0 | 2588 | /* User gives us xfrm_user_policy_info followed by an array of 0 |
2589 | * or more templates. | 2589 | * or more templates. |
2590 | */ | 2590 | */ |
2591 | static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | 2591 | static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, |
2592 | u8 *data, int len, int *dir) | 2592 | u8 *data, int len, int *dir) |
2593 | { | 2593 | { |
2594 | struct net *net = sock_net(sk); | 2594 | struct net *net = sock_net(sk); |
2595 | struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; | 2595 | struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; |
2596 | struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); | 2596 | struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); |
2597 | struct xfrm_policy *xp; | 2597 | struct xfrm_policy *xp; |
2598 | int nr; | 2598 | int nr; |
2599 | 2599 | ||
2600 | switch (sk->sk_family) { | 2600 | switch (sk->sk_family) { |
2601 | case AF_INET: | 2601 | case AF_INET: |
2602 | if (opt != IP_XFRM_POLICY) { | 2602 | if (opt != IP_XFRM_POLICY) { |
2603 | *dir = -EOPNOTSUPP; | 2603 | *dir = -EOPNOTSUPP; |
2604 | return NULL; | 2604 | return NULL; |
2605 | } | 2605 | } |
2606 | break; | 2606 | break; |
2607 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 2607 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
2608 | case AF_INET6: | 2608 | case AF_INET6: |
2609 | if (opt != IPV6_XFRM_POLICY) { | 2609 | if (opt != IPV6_XFRM_POLICY) { |
2610 | *dir = -EOPNOTSUPP; | 2610 | *dir = -EOPNOTSUPP; |
2611 | return NULL; | 2611 | return NULL; |
2612 | } | 2612 | } |
2613 | break; | 2613 | break; |
2614 | #endif | 2614 | #endif |
2615 | default: | 2615 | default: |
2616 | *dir = -EINVAL; | 2616 | *dir = -EINVAL; |
2617 | return NULL; | 2617 | return NULL; |
2618 | } | 2618 | } |
2619 | 2619 | ||
2620 | *dir = -EINVAL; | 2620 | *dir = -EINVAL; |
2621 | 2621 | ||
2622 | if (len < sizeof(*p) || | 2622 | if (len < sizeof(*p) || |
2623 | verify_newpolicy_info(p)) | 2623 | verify_newpolicy_info(p)) |
2624 | return NULL; | 2624 | return NULL; |
2625 | 2625 | ||
2626 | nr = ((len - sizeof(*p)) / sizeof(*ut)); | 2626 | nr = ((len - sizeof(*p)) / sizeof(*ut)); |
2627 | if (validate_tmpl(nr, ut, p->sel.family)) | 2627 | if (validate_tmpl(nr, ut, p->sel.family)) |
2628 | return NULL; | 2628 | return NULL; |
2629 | 2629 | ||
2630 | if (p->dir > XFRM_POLICY_OUT) | 2630 | if (p->dir > XFRM_POLICY_OUT) |
2631 | return NULL; | 2631 | return NULL; |
2632 | 2632 | ||
2633 | xp = xfrm_policy_alloc(net, GFP_ATOMIC); | 2633 | xp = xfrm_policy_alloc(net, GFP_ATOMIC); |
2634 | if (xp == NULL) { | 2634 | if (xp == NULL) { |
2635 | *dir = -ENOBUFS; | 2635 | *dir = -ENOBUFS; |
2636 | return NULL; | 2636 | return NULL; |
2637 | } | 2637 | } |
2638 | 2638 | ||
2639 | copy_from_user_policy(xp, p); | 2639 | copy_from_user_policy(xp, p); |
2640 | xp->type = XFRM_POLICY_TYPE_MAIN; | 2640 | xp->type = XFRM_POLICY_TYPE_MAIN; |
2641 | copy_templates(xp, ut, nr); | 2641 | copy_templates(xp, ut, nr); |
2642 | 2642 | ||
2643 | *dir = p->dir; | 2643 | *dir = p->dir; |
2644 | 2644 | ||
2645 | return xp; | 2645 | return xp; |
2646 | } | 2646 | } |
2647 | 2647 | ||
2648 | static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) | 2648 | static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) |
2649 | { | 2649 | { |
2650 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) | 2650 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) |
2651 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) | 2651 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
2652 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) | 2652 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) |
2653 | + nla_total_size(sizeof(struct xfrm_mark)) | 2653 | + nla_total_size(sizeof(struct xfrm_mark)) |
2654 | + userpolicy_type_attrsize(); | 2654 | + userpolicy_type_attrsize(); |
2655 | } | 2655 | } |
2656 | 2656 | ||
2657 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | 2657 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, |
2658 | int dir, const struct km_event *c) | 2658 | int dir, const struct km_event *c) |
2659 | { | 2659 | { |
2660 | struct xfrm_user_polexpire *upe; | 2660 | struct xfrm_user_polexpire *upe; |
2661 | struct nlmsghdr *nlh; | 2661 | struct nlmsghdr *nlh; |
2662 | int hard = c->data.hard; | 2662 | int hard = c->data.hard; |
2663 | 2663 | ||
2664 | nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0); | 2664 | nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0); |
2665 | if (nlh == NULL) | 2665 | if (nlh == NULL) |
2666 | return -EMSGSIZE; | 2666 | return -EMSGSIZE; |
2667 | 2667 | ||
2668 | upe = nlmsg_data(nlh); | 2668 | upe = nlmsg_data(nlh); |
2669 | copy_to_user_policy(xp, &upe->pol, dir); | 2669 | copy_to_user_policy(xp, &upe->pol, dir); |
2670 | if (copy_to_user_tmpl(xp, skb) < 0) | 2670 | if (copy_to_user_tmpl(xp, skb) < 0) |
2671 | goto nlmsg_failure; | 2671 | goto nlmsg_failure; |
2672 | if (copy_to_user_sec_ctx(xp, skb)) | 2672 | if (copy_to_user_sec_ctx(xp, skb)) |
2673 | goto nlmsg_failure; | 2673 | goto nlmsg_failure; |
2674 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2674 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2675 | goto nlmsg_failure; | 2675 | goto nlmsg_failure; |
2676 | if (xfrm_mark_put(skb, &xp->mark)) | 2676 | if (xfrm_mark_put(skb, &xp->mark)) |
2677 | goto nla_put_failure; | 2677 | goto nla_put_failure; |
2678 | upe->hard = !!hard; | 2678 | upe->hard = !!hard; |
2679 | 2679 | ||
2680 | return nlmsg_end(skb, nlh); | 2680 | return nlmsg_end(skb, nlh); |
2681 | 2681 | ||
2682 | nla_put_failure: | 2682 | nla_put_failure: |
2683 | nlmsg_failure: | 2683 | nlmsg_failure: |
2684 | nlmsg_cancel(skb, nlh); | 2684 | nlmsg_cancel(skb, nlh); |
2685 | return -EMSGSIZE; | 2685 | return -EMSGSIZE; |
2686 | } | 2686 | } |
2687 | 2687 | ||
2688 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) | 2688 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2689 | { | 2689 | { |
2690 | struct net *net = xp_net(xp); | 2690 | struct net *net = xp_net(xp); |
2691 | struct sk_buff *skb; | 2691 | struct sk_buff *skb; |
2692 | 2692 | ||
2693 | skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); | 2693 | skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); |
2694 | if (skb == NULL) | 2694 | if (skb == NULL) |
2695 | return -ENOMEM; | 2695 | return -ENOMEM; |
2696 | 2696 | ||
2697 | if (build_polexpire(skb, xp, dir, c) < 0) | 2697 | if (build_polexpire(skb, xp, dir, c) < 0) |
2698 | BUG(); | 2698 | BUG(); |
2699 | 2699 | ||
2700 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2700 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2701 | } | 2701 | } |
2702 | 2702 | ||
2703 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c) | 2703 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2704 | { | 2704 | { |
2705 | struct net *net = xp_net(xp); | 2705 | struct net *net = xp_net(xp); |
2706 | struct xfrm_userpolicy_info *p; | 2706 | struct xfrm_userpolicy_info *p; |
2707 | struct xfrm_userpolicy_id *id; | 2707 | struct xfrm_userpolicy_id *id; |
2708 | struct nlmsghdr *nlh; | 2708 | struct nlmsghdr *nlh; |
2709 | struct sk_buff *skb; | 2709 | struct sk_buff *skb; |
2710 | int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); | 2710 | int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); |
2711 | int headlen; | 2711 | int headlen; |
2712 | 2712 | ||
2713 | headlen = sizeof(*p); | 2713 | headlen = sizeof(*p); |
2714 | if (c->event == XFRM_MSG_DELPOLICY) { | 2714 | if (c->event == XFRM_MSG_DELPOLICY) { |
2715 | len += nla_total_size(headlen); | 2715 | len += nla_total_size(headlen); |
2716 | headlen = sizeof(*id); | 2716 | headlen = sizeof(*id); |
2717 | } | 2717 | } |
2718 | len += userpolicy_type_attrsize(); | 2718 | len += userpolicy_type_attrsize(); |
2719 | len += nla_total_size(sizeof(struct xfrm_mark)); | 2719 | len += nla_total_size(sizeof(struct xfrm_mark)); |
2720 | len += NLMSG_ALIGN(headlen); | 2720 | len += NLMSG_ALIGN(headlen); |
2721 | 2721 | ||
2722 | skb = nlmsg_new(len, GFP_ATOMIC); | 2722 | skb = nlmsg_new(len, GFP_ATOMIC); |
2723 | if (skb == NULL) | 2723 | if (skb == NULL) |
2724 | return -ENOMEM; | 2724 | return -ENOMEM; |
2725 | 2725 | ||
2726 | nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); | 2726 | nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); |
2727 | if (nlh == NULL) | 2727 | if (nlh == NULL) |
2728 | goto nlmsg_failure; | 2728 | goto nlmsg_failure; |
2729 | 2729 | ||
2730 | p = nlmsg_data(nlh); | 2730 | p = nlmsg_data(nlh); |
2731 | if (c->event == XFRM_MSG_DELPOLICY) { | 2731 | if (c->event == XFRM_MSG_DELPOLICY) { |
2732 | struct nlattr *attr; | 2732 | struct nlattr *attr; |
2733 | 2733 | ||
2734 | id = nlmsg_data(nlh); | 2734 | id = nlmsg_data(nlh); |
2735 | memset(id, 0, sizeof(*id)); | 2735 | memset(id, 0, sizeof(*id)); |
2736 | id->dir = dir; | 2736 | id->dir = dir; |
2737 | if (c->data.byid) | 2737 | if (c->data.byid) |
2738 | id->index = xp->index; | 2738 | id->index = xp->index; |
2739 | else | 2739 | else |
2740 | memcpy(&id->sel, &xp->selector, sizeof(id->sel)); | 2740 | memcpy(&id->sel, &xp->selector, sizeof(id->sel)); |
2741 | 2741 | ||
2742 | attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p)); | 2742 | attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p)); |
2743 | if (attr == NULL) | 2743 | if (attr == NULL) |
2744 | goto nlmsg_failure; | 2744 | goto nlmsg_failure; |
2745 | 2745 | ||
2746 | p = nla_data(attr); | 2746 | p = nla_data(attr); |
2747 | } | 2747 | } |
2748 | 2748 | ||
2749 | copy_to_user_policy(xp, p, dir); | 2749 | copy_to_user_policy(xp, p, dir); |
2750 | if (copy_to_user_tmpl(xp, skb) < 0) | 2750 | if (copy_to_user_tmpl(xp, skb) < 0) |
2751 | goto nlmsg_failure; | 2751 | goto nlmsg_failure; |
2752 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2752 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2753 | goto nlmsg_failure; | 2753 | goto nlmsg_failure; |
2754 | 2754 | ||
2755 | if (xfrm_mark_put(skb, &xp->mark)) | 2755 | if (xfrm_mark_put(skb, &xp->mark)) |
2756 | goto nla_put_failure; | 2756 | goto nla_put_failure; |
2757 | 2757 | ||
2758 | nlmsg_end(skb, nlh); | 2758 | nlmsg_end(skb, nlh); |
2759 | 2759 | ||
2760 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2760 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2761 | 2761 | ||
2762 | nla_put_failure: | 2762 | nla_put_failure: |
2763 | nlmsg_failure: | 2763 | nlmsg_failure: |
2764 | kfree_skb(skb); | 2764 | kfree_skb(skb); |
2765 | return -1; | 2765 | return -1; |
2766 | } | 2766 | } |
2767 | 2767 | ||
2768 | static int xfrm_notify_policy_flush(const struct km_event *c) | 2768 | static int xfrm_notify_policy_flush(const struct km_event *c) |
2769 | { | 2769 | { |
2770 | struct net *net = c->net; | 2770 | struct net *net = c->net; |
2771 | struct nlmsghdr *nlh; | 2771 | struct nlmsghdr *nlh; |
2772 | struct sk_buff *skb; | 2772 | struct sk_buff *skb; |
2773 | 2773 | ||
2774 | skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC); | 2774 | skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC); |
2775 | if (skb == NULL) | 2775 | if (skb == NULL) |
2776 | return -ENOMEM; | 2776 | return -ENOMEM; |
2777 | 2777 | ||
2778 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0); | 2778 | nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0); |
2779 | if (nlh == NULL) | 2779 | if (nlh == NULL) |
2780 | goto nlmsg_failure; | 2780 | goto nlmsg_failure; |
2781 | if (copy_to_user_policy_type(c->data.type, skb) < 0) | 2781 | if (copy_to_user_policy_type(c->data.type, skb) < 0) |
2782 | goto nlmsg_failure; | 2782 | goto nlmsg_failure; |
2783 | 2783 | ||
2784 | nlmsg_end(skb, nlh); | 2784 | nlmsg_end(skb, nlh); |
2785 | 2785 | ||
2786 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2786 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2787 | 2787 | ||
2788 | nlmsg_failure: | 2788 | nlmsg_failure: |
2789 | kfree_skb(skb); | 2789 | kfree_skb(skb); |
2790 | return -1; | 2790 | return -1; |
2791 | } | 2791 | } |
2792 | 2792 | ||
2793 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) | 2793 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2794 | { | 2794 | { |
2795 | 2795 | ||
2796 | switch (c->event) { | 2796 | switch (c->event) { |
2797 | case XFRM_MSG_NEWPOLICY: | 2797 | case XFRM_MSG_NEWPOLICY: |
2798 | case XFRM_MSG_UPDPOLICY: | 2798 | case XFRM_MSG_UPDPOLICY: |
2799 | case XFRM_MSG_DELPOLICY: | 2799 | case XFRM_MSG_DELPOLICY: |
2800 | return xfrm_notify_policy(xp, dir, c); | 2800 | return xfrm_notify_policy(xp, dir, c); |
2801 | case XFRM_MSG_FLUSHPOLICY: | 2801 | case XFRM_MSG_FLUSHPOLICY: |
2802 | return xfrm_notify_policy_flush(c); | 2802 | return xfrm_notify_policy_flush(c); |
2803 | case XFRM_MSG_POLEXPIRE: | 2803 | case XFRM_MSG_POLEXPIRE: |
2804 | return xfrm_exp_policy_notify(xp, dir, c); | 2804 | return xfrm_exp_policy_notify(xp, dir, c); |
2805 | default: | 2805 | default: |
2806 | printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d\n", | 2806 | printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d\n", |
2807 | c->event); | 2807 | c->event); |
2808 | } | 2808 | } |
2809 | 2809 | ||
2810 | return 0; | 2810 | return 0; |
2811 | 2811 | ||
2812 | } | 2812 | } |
2813 | 2813 | ||
2814 | static inline size_t xfrm_report_msgsize(void) | 2814 | static inline size_t xfrm_report_msgsize(void) |
2815 | { | 2815 | { |
2816 | return NLMSG_ALIGN(sizeof(struct xfrm_user_report)); | 2816 | return NLMSG_ALIGN(sizeof(struct xfrm_user_report)); |
2817 | } | 2817 | } |
2818 | 2818 | ||
2819 | static int build_report(struct sk_buff *skb, u8 proto, | 2819 | static int build_report(struct sk_buff *skb, u8 proto, |
2820 | struct xfrm_selector *sel, xfrm_address_t *addr) | 2820 | struct xfrm_selector *sel, xfrm_address_t *addr) |
2821 | { | 2821 | { |
2822 | struct xfrm_user_report *ur; | 2822 | struct xfrm_user_report *ur; |
2823 | struct nlmsghdr *nlh; | 2823 | struct nlmsghdr *nlh; |
2824 | 2824 | ||
2825 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0); | 2825 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0); |
2826 | if (nlh == NULL) | 2826 | if (nlh == NULL) |
2827 | return -EMSGSIZE; | 2827 | return -EMSGSIZE; |
2828 | 2828 | ||
2829 | ur = nlmsg_data(nlh); | 2829 | ur = nlmsg_data(nlh); |
2830 | ur->proto = proto; | 2830 | ur->proto = proto; |
2831 | memcpy(&ur->sel, sel, sizeof(ur->sel)); | 2831 | memcpy(&ur->sel, sel, sizeof(ur->sel)); |
2832 | 2832 | ||
2833 | if (addr) | 2833 | if (addr) |
2834 | NLA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr); | 2834 | NLA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr); |
2835 | 2835 | ||
2836 | return nlmsg_end(skb, nlh); | 2836 | return nlmsg_end(skb, nlh); |
2837 | 2837 | ||
2838 | nla_put_failure: | 2838 | nla_put_failure: |
2839 | nlmsg_cancel(skb, nlh); | 2839 | nlmsg_cancel(skb, nlh); |
2840 | return -EMSGSIZE; | 2840 | return -EMSGSIZE; |
2841 | } | 2841 | } |
2842 | 2842 | ||
2843 | static int xfrm_send_report(struct net *net, u8 proto, | 2843 | static int xfrm_send_report(struct net *net, u8 proto, |
2844 | struct xfrm_selector *sel, xfrm_address_t *addr) | 2844 | struct xfrm_selector *sel, xfrm_address_t *addr) |
2845 | { | 2845 | { |
2846 | struct sk_buff *skb; | 2846 | struct sk_buff *skb; |
2847 | 2847 | ||
2848 | skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC); | 2848 | skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC); |
2849 | if (skb == NULL) | 2849 | if (skb == NULL) |
2850 | return -ENOMEM; | 2850 | return -ENOMEM; |
2851 | 2851 | ||
2852 | if (build_report(skb, proto, sel, addr) < 0) | 2852 | if (build_report(skb, proto, sel, addr) < 0) |
2853 | BUG(); | 2853 | BUG(); |
2854 | 2854 | ||
2855 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); | 2855 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); |
2856 | } | 2856 | } |
2857 | 2857 | ||
2858 | static inline size_t xfrm_mapping_msgsize(void) | 2858 | static inline size_t xfrm_mapping_msgsize(void) |
2859 | { | 2859 | { |
2860 | return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); | 2860 | return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); |
2861 | } | 2861 | } |
2862 | 2862 | ||
2863 | static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, | 2863 | static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, |
2864 | xfrm_address_t *new_saddr, __be16 new_sport) | 2864 | xfrm_address_t *new_saddr, __be16 new_sport) |
2865 | { | 2865 | { |
2866 | struct xfrm_user_mapping *um; | 2866 | struct xfrm_user_mapping *um; |
2867 | struct nlmsghdr *nlh; | 2867 | struct nlmsghdr *nlh; |
2868 | 2868 | ||
2869 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); | 2869 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); |
2870 | if (nlh == NULL) | 2870 | if (nlh == NULL) |
2871 | return -EMSGSIZE; | 2871 | return -EMSGSIZE; |
2872 | 2872 | ||
2873 | um = nlmsg_data(nlh); | 2873 | um = nlmsg_data(nlh); |
2874 | 2874 | ||
2875 | memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); | 2875 | memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); |
2876 | um->id.spi = x->id.spi; | 2876 | um->id.spi = x->id.spi; |
2877 | um->id.family = x->props.family; | 2877 | um->id.family = x->props.family; |
2878 | um->id.proto = x->id.proto; | 2878 | um->id.proto = x->id.proto; |
2879 | memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); | 2879 | memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); |
2880 | memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); | 2880 | memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); |
2881 | um->new_sport = new_sport; | 2881 | um->new_sport = new_sport; |
2882 | um->old_sport = x->encap->encap_sport; | 2882 | um->old_sport = x->encap->encap_sport; |
2883 | um->reqid = x->props.reqid; | 2883 | um->reqid = x->props.reqid; |
2884 | 2884 | ||
2885 | return nlmsg_end(skb, nlh); | 2885 | return nlmsg_end(skb, nlh); |
2886 | } | 2886 | } |
2887 | 2887 | ||
2888 | static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | 2888 | static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, |
2889 | __be16 sport) | 2889 | __be16 sport) |
2890 | { | 2890 | { |
2891 | struct net *net = xs_net(x); | 2891 | struct net *net = xs_net(x); |
2892 | struct sk_buff *skb; | 2892 | struct sk_buff *skb; |
2893 | 2893 | ||
2894 | if (x->id.proto != IPPROTO_ESP) | 2894 | if (x->id.proto != IPPROTO_ESP) |
2895 | return -EINVAL; | 2895 | return -EINVAL; |
2896 | 2896 | ||
2897 | if (!x->encap) | 2897 | if (!x->encap) |
2898 | return -EINVAL; | 2898 | return -EINVAL; |
2899 | 2899 | ||
2900 | skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); | 2900 | skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); |
2901 | if (skb == NULL) | 2901 | if (skb == NULL) |
2902 | return -ENOMEM; | 2902 | return -ENOMEM; |
2903 | 2903 | ||
2904 | if (build_mapping(skb, x, ipaddr, sport) < 0) | 2904 | if (build_mapping(skb, x, ipaddr, sport) < 0) |
2905 | BUG(); | 2905 | BUG(); |
2906 | 2906 | ||
2907 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); | 2907 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); |
2908 | } | 2908 | } |
2909 | 2909 | ||
2910 | static struct xfrm_mgr netlink_mgr = { | 2910 | static struct xfrm_mgr netlink_mgr = { |
2911 | .id = "netlink", | 2911 | .id = "netlink", |
2912 | .notify = xfrm_send_state_notify, | 2912 | .notify = xfrm_send_state_notify, |
2913 | .acquire = xfrm_send_acquire, | 2913 | .acquire = xfrm_send_acquire, |
2914 | .compile_policy = xfrm_compile_policy, | 2914 | .compile_policy = xfrm_compile_policy, |
2915 | .notify_policy = xfrm_send_policy_notify, | 2915 | .notify_policy = xfrm_send_policy_notify, |
2916 | .report = xfrm_send_report, | 2916 | .report = xfrm_send_report, |
2917 | .migrate = xfrm_send_migrate, | 2917 | .migrate = xfrm_send_migrate, |
2918 | .new_mapping = xfrm_send_mapping, | 2918 | .new_mapping = xfrm_send_mapping, |
2919 | }; | 2919 | }; |
2920 | 2920 | ||
2921 | static int __net_init xfrm_user_net_init(struct net *net) | 2921 | static int __net_init xfrm_user_net_init(struct net *net) |
2922 | { | 2922 | { |
2923 | struct sock *nlsk; | 2923 | struct sock *nlsk; |
2924 | 2924 | ||
2925 | nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX, | 2925 | nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX, |
2926 | xfrm_netlink_rcv, NULL, THIS_MODULE); | 2926 | xfrm_netlink_rcv, NULL, THIS_MODULE); |
2927 | if (nlsk == NULL) | 2927 | if (nlsk == NULL) |
2928 | return -ENOMEM; | 2928 | return -ENOMEM; |
2929 | net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ | 2929 | net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ |
2930 | rcu_assign_pointer(net->xfrm.nlsk, nlsk); | 2930 | rcu_assign_pointer(net->xfrm.nlsk, nlsk); |
2931 | return 0; | 2931 | return 0; |
2932 | } | 2932 | } |
2933 | 2933 | ||
2934 | static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list) | 2934 | static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list) |
2935 | { | 2935 | { |
2936 | struct net *net; | 2936 | struct net *net; |
2937 | list_for_each_entry(net, net_exit_list, exit_list) | 2937 | list_for_each_entry(net, net_exit_list, exit_list) |
2938 | rcu_assign_pointer(net->xfrm.nlsk, NULL); | 2938 | rcu_assign_pointer(net->xfrm.nlsk, NULL); |
2939 | synchronize_net(); | 2939 | synchronize_net(); |
2940 | list_for_each_entry(net, net_exit_list, exit_list) | 2940 | list_for_each_entry(net, net_exit_list, exit_list) |
2941 | netlink_kernel_release(net->xfrm.nlsk_stash); | 2941 | netlink_kernel_release(net->xfrm.nlsk_stash); |
2942 | } | 2942 | } |
2943 | 2943 | ||
2944 | static struct pernet_operations xfrm_user_net_ops = { | 2944 | static struct pernet_operations xfrm_user_net_ops = { |
2945 | .init = xfrm_user_net_init, | 2945 | .init = xfrm_user_net_init, |
2946 | .exit_batch = xfrm_user_net_exit, | 2946 | .exit_batch = xfrm_user_net_exit, |
2947 | }; | 2947 | }; |
2948 | 2948 | ||
2949 | static int __init xfrm_user_init(void) | 2949 | static int __init xfrm_user_init(void) |
2950 | { | 2950 | { |
2951 | int rv; | 2951 | int rv; |
2952 | 2952 | ||
2953 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); | 2953 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); |
2954 | 2954 | ||
2955 | rv = register_pernet_subsys(&xfrm_user_net_ops); | 2955 | rv = register_pernet_subsys(&xfrm_user_net_ops); |
2956 | if (rv < 0) | 2956 | if (rv < 0) |
2957 | return rv; | 2957 | return rv; |
2958 | rv = xfrm_register_km(&netlink_mgr); | 2958 | rv = xfrm_register_km(&netlink_mgr); |
2959 | if (rv < 0) | 2959 | if (rv < 0) |
2960 | unregister_pernet_subsys(&xfrm_user_net_ops); | 2960 | unregister_pernet_subsys(&xfrm_user_net_ops); |
2961 | return rv; | 2961 | return rv; |
2962 | } | 2962 | } |
2963 | 2963 | ||
2964 | static void __exit xfrm_user_exit(void) | 2964 | static void __exit xfrm_user_exit(void) |
2965 | { | 2965 | { |
2966 | xfrm_unregister_km(&netlink_mgr); | 2966 | xfrm_unregister_km(&netlink_mgr); |
2967 | unregister_pernet_subsys(&xfrm_user_net_ops); | 2967 | unregister_pernet_subsys(&xfrm_user_net_ops); |
2968 | } | 2968 | } |
2969 | 2969 | ||
2970 | module_init(xfrm_user_init); | 2970 | module_init(xfrm_user_init); |
2971 | module_exit(xfrm_user_exit); | 2971 | module_exit(xfrm_user_exit); |
2972 | MODULE_LICENSE("GPL"); | 2972 | MODULE_LICENSE("GPL"); |
2973 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); | 2973 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); |
2974 | 2974 | ||
2975 | 2975 |
security/capability.c
1 | /* | 1 | /* |
2 | * Capabilities Linux Security Module | 2 | * Capabilities Linux Security Module |
3 | * | 3 | * |
4 | * This is the default security module in case no other module is loaded. | 4 | * This is the default security module in case no other module is loaded. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | 14 | ||
15 | static int cap_syslog(int type) | 15 | static int cap_syslog(int type) |
16 | { | 16 | { |
17 | return 0; | 17 | return 0; |
18 | } | 18 | } |
19 | 19 | ||
20 | static int cap_quotactl(int cmds, int type, int id, struct super_block *sb) | 20 | static int cap_quotactl(int cmds, int type, int id, struct super_block *sb) |
21 | { | 21 | { |
22 | return 0; | 22 | return 0; |
23 | } | 23 | } |
24 | 24 | ||
25 | static int cap_quota_on(struct dentry *dentry) | 25 | static int cap_quota_on(struct dentry *dentry) |
26 | { | 26 | { |
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
30 | static int cap_bprm_check_security(struct linux_binprm *bprm) | 30 | static int cap_bprm_check_security(struct linux_binprm *bprm) |
31 | { | 31 | { |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | static void cap_bprm_committing_creds(struct linux_binprm *bprm) | 35 | static void cap_bprm_committing_creds(struct linux_binprm *bprm) |
36 | { | 36 | { |
37 | } | 37 | } |
38 | 38 | ||
39 | static void cap_bprm_committed_creds(struct linux_binprm *bprm) | 39 | static void cap_bprm_committed_creds(struct linux_binprm *bprm) |
40 | { | 40 | { |
41 | } | 41 | } |
42 | 42 | ||
43 | static int cap_sb_alloc_security(struct super_block *sb) | 43 | static int cap_sb_alloc_security(struct super_block *sb) |
44 | { | 44 | { |
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | static void cap_sb_free_security(struct super_block *sb) | 48 | static void cap_sb_free_security(struct super_block *sb) |
49 | { | 49 | { |
50 | } | 50 | } |
51 | 51 | ||
52 | static int cap_sb_copy_data(char *orig, char *copy) | 52 | static int cap_sb_copy_data(char *orig, char *copy) |
53 | { | 53 | { |
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | static int cap_sb_remount(struct super_block *sb, void *data) | 57 | static int cap_sb_remount(struct super_block *sb, void *data) |
58 | { | 58 | { |
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) | 62 | static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) |
63 | { | 63 | { |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | static int cap_sb_show_options(struct seq_file *m, struct super_block *sb) | 67 | static int cap_sb_show_options(struct seq_file *m, struct super_block *sb) |
68 | { | 68 | { |
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int cap_sb_statfs(struct dentry *dentry) | 72 | static int cap_sb_statfs(struct dentry *dentry) |
73 | { | 73 | { |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int cap_sb_mount(char *dev_name, struct path *path, char *type, | 77 | static int cap_sb_mount(char *dev_name, struct path *path, char *type, |
78 | unsigned long flags, void *data) | 78 | unsigned long flags, void *data) |
79 | { | 79 | { |
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int cap_sb_umount(struct vfsmount *mnt, int flags) | 83 | static int cap_sb_umount(struct vfsmount *mnt, int flags) |
84 | { | 84 | { |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) | 88 | static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) |
89 | { | 89 | { |
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int cap_sb_set_mnt_opts(struct super_block *sb, | 93 | static int cap_sb_set_mnt_opts(struct super_block *sb, |
94 | struct security_mnt_opts *opts) | 94 | struct security_mnt_opts *opts) |
95 | { | 95 | { |
96 | if (unlikely(opts->num_mnt_opts)) | 96 | if (unlikely(opts->num_mnt_opts)) |
97 | return -EOPNOTSUPP; | 97 | return -EOPNOTSUPP; |
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, | 101 | static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, |
102 | struct super_block *newsb) | 102 | struct super_block *newsb) |
103 | { | 103 | { |
104 | } | 104 | } |
105 | 105 | ||
106 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 106 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
107 | { | 107 | { |
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int cap_inode_alloc_security(struct inode *inode) | 111 | static int cap_inode_alloc_security(struct inode *inode) |
112 | { | 112 | { |
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static void cap_inode_free_security(struct inode *inode) | 116 | static void cap_inode_free_security(struct inode *inode) |
117 | { | 117 | { |
118 | } | 118 | } |
119 | 119 | ||
120 | static int cap_inode_init_security(struct inode *inode, struct inode *dir, | 120 | static int cap_inode_init_security(struct inode *inode, struct inode *dir, |
121 | const struct qstr *qstr, char **name, | 121 | const struct qstr *qstr, char **name, |
122 | void **value, size_t *len) | 122 | void **value, size_t *len) |
123 | { | 123 | { |
124 | return -EOPNOTSUPP; | 124 | return -EOPNOTSUPP; |
125 | } | 125 | } |
126 | 126 | ||
127 | static int cap_inode_create(struct inode *inode, struct dentry *dentry, | 127 | static int cap_inode_create(struct inode *inode, struct dentry *dentry, |
128 | int mask) | 128 | int mask) |
129 | { | 129 | { |
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static int cap_inode_link(struct dentry *old_dentry, struct inode *inode, | 133 | static int cap_inode_link(struct dentry *old_dentry, struct inode *inode, |
134 | struct dentry *new_dentry) | 134 | struct dentry *new_dentry) |
135 | { | 135 | { |
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | static int cap_inode_unlink(struct inode *inode, struct dentry *dentry) | 139 | static int cap_inode_unlink(struct inode *inode, struct dentry *dentry) |
140 | { | 140 | { |
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int cap_inode_symlink(struct inode *inode, struct dentry *dentry, | 144 | static int cap_inode_symlink(struct inode *inode, struct dentry *dentry, |
145 | const char *name) | 145 | const char *name) |
146 | { | 146 | { |
147 | return 0; | 147 | return 0; |
148 | } | 148 | } |
149 | 149 | ||
150 | static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry, | 150 | static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry, |
151 | int mask) | 151 | int mask) |
152 | { | 152 | { |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry) | 156 | static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry) |
157 | { | 157 | { |
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | static int cap_inode_mknod(struct inode *inode, struct dentry *dentry, | 161 | static int cap_inode_mknod(struct inode *inode, struct dentry *dentry, |
162 | int mode, dev_t dev) | 162 | int mode, dev_t dev) |
163 | { | 163 | { |
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry, | 167 | static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry, |
168 | struct inode *new_inode, struct dentry *new_dentry) | 168 | struct inode *new_inode, struct dentry *new_dentry) |
169 | { | 169 | { |
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | static int cap_inode_readlink(struct dentry *dentry) | 173 | static int cap_inode_readlink(struct dentry *dentry) |
174 | { | 174 | { |
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int cap_inode_follow_link(struct dentry *dentry, | 178 | static int cap_inode_follow_link(struct dentry *dentry, |
179 | struct nameidata *nameidata) | 179 | struct nameidata *nameidata) |
180 | { | 180 | { |
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | static int cap_inode_permission(struct inode *inode, int mask) | 184 | static int cap_inode_permission(struct inode *inode, int mask) |
185 | { | 185 | { |
186 | return 0; | 186 | return 0; |
187 | } | 187 | } |
188 | 188 | ||
189 | static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 189 | static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
190 | { | 190 | { |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | 193 | ||
194 | static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 194 | static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
195 | { | 195 | { |
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | 198 | ||
199 | static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, | 199 | static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, |
200 | const void *value, size_t size, int flags) | 200 | const void *value, size_t size, int flags) |
201 | { | 201 | { |
202 | } | 202 | } |
203 | 203 | ||
204 | static int cap_inode_getxattr(struct dentry *dentry, const char *name) | 204 | static int cap_inode_getxattr(struct dentry *dentry, const char *name) |
205 | { | 205 | { |
206 | return 0; | 206 | return 0; |
207 | } | 207 | } |
208 | 208 | ||
209 | static int cap_inode_listxattr(struct dentry *dentry) | 209 | static int cap_inode_listxattr(struct dentry *dentry) |
210 | { | 210 | { |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | 213 | ||
214 | static int cap_inode_getsecurity(const struct inode *inode, const char *name, | 214 | static int cap_inode_getsecurity(const struct inode *inode, const char *name, |
215 | void **buffer, bool alloc) | 215 | void **buffer, bool alloc) |
216 | { | 216 | { |
217 | return -EOPNOTSUPP; | 217 | return -EOPNOTSUPP; |
218 | } | 218 | } |
219 | 219 | ||
220 | static int cap_inode_setsecurity(struct inode *inode, const char *name, | 220 | static int cap_inode_setsecurity(struct inode *inode, const char *name, |
221 | const void *value, size_t size, int flags) | 221 | const void *value, size_t size, int flags) |
222 | { | 222 | { |
223 | return -EOPNOTSUPP; | 223 | return -EOPNOTSUPP; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int cap_inode_listsecurity(struct inode *inode, char *buffer, | 226 | static int cap_inode_listsecurity(struct inode *inode, char *buffer, |
227 | size_t buffer_size) | 227 | size_t buffer_size) |
228 | { | 228 | { |
229 | return 0; | 229 | return 0; |
230 | } | 230 | } |
231 | 231 | ||
232 | static void cap_inode_getsecid(const struct inode *inode, u32 *secid) | 232 | static void cap_inode_getsecid(const struct inode *inode, u32 *secid) |
233 | { | 233 | { |
234 | *secid = 0; | 234 | *secid = 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | #ifdef CONFIG_SECURITY_PATH | 237 | #ifdef CONFIG_SECURITY_PATH |
238 | static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode, | 238 | static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode, |
239 | unsigned int dev) | 239 | unsigned int dev) |
240 | { | 240 | { |
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode) | 244 | static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode) |
245 | { | 245 | { |
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int cap_path_rmdir(struct path *dir, struct dentry *dentry) | 249 | static int cap_path_rmdir(struct path *dir, struct dentry *dentry) |
250 | { | 250 | { |
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int cap_path_unlink(struct path *dir, struct dentry *dentry) | 254 | static int cap_path_unlink(struct path *dir, struct dentry *dentry) |
255 | { | 255 | { |
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | static int cap_path_symlink(struct path *dir, struct dentry *dentry, | 259 | static int cap_path_symlink(struct path *dir, struct dentry *dentry, |
260 | const char *old_name) | 260 | const char *old_name) |
261 | { | 261 | { |
262 | return 0; | 262 | return 0; |
263 | } | 263 | } |
264 | 264 | ||
265 | static int cap_path_link(struct dentry *old_dentry, struct path *new_dir, | 265 | static int cap_path_link(struct dentry *old_dentry, struct path *new_dir, |
266 | struct dentry *new_dentry) | 266 | struct dentry *new_dentry) |
267 | { | 267 | { |
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | static int cap_path_rename(struct path *old_path, struct dentry *old_dentry, | 271 | static int cap_path_rename(struct path *old_path, struct dentry *old_dentry, |
272 | struct path *new_path, struct dentry *new_dentry) | 272 | struct path *new_path, struct dentry *new_dentry) |
273 | { | 273 | { |
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | static int cap_path_truncate(struct path *path) | 277 | static int cap_path_truncate(struct path *path) |
278 | { | 278 | { |
279 | return 0; | 279 | return 0; |
280 | } | 280 | } |
281 | 281 | ||
282 | static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | 282 | static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt, |
283 | mode_t mode) | 283 | mode_t mode) |
284 | { | 284 | { |
285 | return 0; | 285 | return 0; |
286 | } | 286 | } |
287 | 287 | ||
288 | static int cap_path_chown(struct path *path, uid_t uid, gid_t gid) | 288 | static int cap_path_chown(struct path *path, uid_t uid, gid_t gid) |
289 | { | 289 | { |
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
292 | 292 | ||
293 | static int cap_path_chroot(struct path *root) | 293 | static int cap_path_chroot(struct path *root) |
294 | { | 294 | { |
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | #endif | 297 | #endif |
298 | 298 | ||
299 | static int cap_file_permission(struct file *file, int mask) | 299 | static int cap_file_permission(struct file *file, int mask) |
300 | { | 300 | { |
301 | return 0; | 301 | return 0; |
302 | } | 302 | } |
303 | 303 | ||
304 | static int cap_file_alloc_security(struct file *file) | 304 | static int cap_file_alloc_security(struct file *file) |
305 | { | 305 | { |
306 | return 0; | 306 | return 0; |
307 | } | 307 | } |
308 | 308 | ||
309 | static void cap_file_free_security(struct file *file) | 309 | static void cap_file_free_security(struct file *file) |
310 | { | 310 | { |
311 | } | 311 | } |
312 | 312 | ||
313 | static int cap_file_ioctl(struct file *file, unsigned int command, | 313 | static int cap_file_ioctl(struct file *file, unsigned int command, |
314 | unsigned long arg) | 314 | unsigned long arg) |
315 | { | 315 | { |
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
318 | 318 | ||
319 | static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 319 | static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
320 | unsigned long prot) | 320 | unsigned long prot) |
321 | { | 321 | { |
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
325 | static int cap_file_lock(struct file *file, unsigned int cmd) | 325 | static int cap_file_lock(struct file *file, unsigned int cmd) |
326 | { | 326 | { |
327 | return 0; | 327 | return 0; |
328 | } | 328 | } |
329 | 329 | ||
330 | static int cap_file_fcntl(struct file *file, unsigned int cmd, | 330 | static int cap_file_fcntl(struct file *file, unsigned int cmd, |
331 | unsigned long arg) | 331 | unsigned long arg) |
332 | { | 332 | { |
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static int cap_file_set_fowner(struct file *file) | 336 | static int cap_file_set_fowner(struct file *file) |
337 | { | 337 | { |
338 | return 0; | 338 | return 0; |
339 | } | 339 | } |
340 | 340 | ||
341 | static int cap_file_send_sigiotask(struct task_struct *tsk, | 341 | static int cap_file_send_sigiotask(struct task_struct *tsk, |
342 | struct fown_struct *fown, int sig) | 342 | struct fown_struct *fown, int sig) |
343 | { | 343 | { |
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | 346 | ||
347 | static int cap_file_receive(struct file *file) | 347 | static int cap_file_receive(struct file *file) |
348 | { | 348 | { |
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
352 | static int cap_dentry_open(struct file *file, const struct cred *cred) | 352 | static int cap_dentry_open(struct file *file, const struct cred *cred) |
353 | { | 353 | { |
354 | return 0; | 354 | return 0; |
355 | } | 355 | } |
356 | 356 | ||
357 | static int cap_task_create(unsigned long clone_flags) | 357 | static int cap_task_create(unsigned long clone_flags) |
358 | { | 358 | { |
359 | return 0; | 359 | return 0; |
360 | } | 360 | } |
361 | 361 | ||
362 | static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 362 | static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
363 | { | 363 | { |
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | static void cap_cred_free(struct cred *cred) | 367 | static void cap_cred_free(struct cred *cred) |
368 | { | 368 | { |
369 | } | 369 | } |
370 | 370 | ||
371 | static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) | 371 | static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) |
372 | { | 372 | { |
373 | return 0; | 373 | return 0; |
374 | } | 374 | } |
375 | 375 | ||
376 | static void cap_cred_transfer(struct cred *new, const struct cred *old) | 376 | static void cap_cred_transfer(struct cred *new, const struct cred *old) |
377 | { | 377 | { |
378 | } | 378 | } |
379 | 379 | ||
380 | static int cap_kernel_act_as(struct cred *new, u32 secid) | 380 | static int cap_kernel_act_as(struct cred *new, u32 secid) |
381 | { | 381 | { |
382 | return 0; | 382 | return 0; |
383 | } | 383 | } |
384 | 384 | ||
385 | static int cap_kernel_create_files_as(struct cred *new, struct inode *inode) | 385 | static int cap_kernel_create_files_as(struct cred *new, struct inode *inode) |
386 | { | 386 | { |
387 | return 0; | 387 | return 0; |
388 | } | 388 | } |
389 | 389 | ||
390 | static int cap_kernel_module_request(char *kmod_name) | 390 | static int cap_kernel_module_request(char *kmod_name) |
391 | { | 391 | { |
392 | return 0; | 392 | return 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) | 395 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) |
396 | { | 396 | { |
397 | return 0; | 397 | return 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | static int cap_task_getpgid(struct task_struct *p) | 400 | static int cap_task_getpgid(struct task_struct *p) |
401 | { | 401 | { |
402 | return 0; | 402 | return 0; |
403 | } | 403 | } |
404 | 404 | ||
405 | static int cap_task_getsid(struct task_struct *p) | 405 | static int cap_task_getsid(struct task_struct *p) |
406 | { | 406 | { |
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static void cap_task_getsecid(struct task_struct *p, u32 *secid) | 410 | static void cap_task_getsecid(struct task_struct *p, u32 *secid) |
411 | { | 411 | { |
412 | *secid = 0; | 412 | *secid = 0; |
413 | } | 413 | } |
414 | 414 | ||
415 | static int cap_task_getioprio(struct task_struct *p) | 415 | static int cap_task_getioprio(struct task_struct *p) |
416 | { | 416 | { |
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | static int cap_task_setrlimit(struct task_struct *p, unsigned int resource, | 420 | static int cap_task_setrlimit(struct task_struct *p, unsigned int resource, |
421 | struct rlimit *new_rlim) | 421 | struct rlimit *new_rlim) |
422 | { | 422 | { |
423 | return 0; | 423 | return 0; |
424 | } | 424 | } |
425 | 425 | ||
426 | static int cap_task_getscheduler(struct task_struct *p) | 426 | static int cap_task_getscheduler(struct task_struct *p) |
427 | { | 427 | { |
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | static int cap_task_movememory(struct task_struct *p) | 431 | static int cap_task_movememory(struct task_struct *p) |
432 | { | 432 | { |
433 | return 0; | 433 | return 0; |
434 | } | 434 | } |
435 | 435 | ||
436 | static int cap_task_wait(struct task_struct *p) | 436 | static int cap_task_wait(struct task_struct *p) |
437 | { | 437 | { |
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | static int cap_task_kill(struct task_struct *p, struct siginfo *info, | 441 | static int cap_task_kill(struct task_struct *p, struct siginfo *info, |
442 | int sig, u32 secid) | 442 | int sig, u32 secid) |
443 | { | 443 | { |
444 | return 0; | 444 | return 0; |
445 | } | 445 | } |
446 | 446 | ||
447 | static void cap_task_to_inode(struct task_struct *p, struct inode *inode) | 447 | static void cap_task_to_inode(struct task_struct *p, struct inode *inode) |
448 | { | 448 | { |
449 | } | 449 | } |
450 | 450 | ||
451 | static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | 451 | static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag) |
452 | { | 452 | { |
453 | return 0; | 453 | return 0; |
454 | } | 454 | } |
455 | 455 | ||
456 | static void cap_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | 456 | static void cap_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) |
457 | { | 457 | { |
458 | *secid = 0; | 458 | *secid = 0; |
459 | } | 459 | } |
460 | 460 | ||
461 | static int cap_msg_msg_alloc_security(struct msg_msg *msg) | 461 | static int cap_msg_msg_alloc_security(struct msg_msg *msg) |
462 | { | 462 | { |
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | 465 | ||
466 | static void cap_msg_msg_free_security(struct msg_msg *msg) | 466 | static void cap_msg_msg_free_security(struct msg_msg *msg) |
467 | { | 467 | { |
468 | } | 468 | } |
469 | 469 | ||
470 | static int cap_msg_queue_alloc_security(struct msg_queue *msq) | 470 | static int cap_msg_queue_alloc_security(struct msg_queue *msq) |
471 | { | 471 | { |
472 | return 0; | 472 | return 0; |
473 | } | 473 | } |
474 | 474 | ||
475 | static void cap_msg_queue_free_security(struct msg_queue *msq) | 475 | static void cap_msg_queue_free_security(struct msg_queue *msq) |
476 | { | 476 | { |
477 | } | 477 | } |
478 | 478 | ||
479 | static int cap_msg_queue_associate(struct msg_queue *msq, int msqflg) | 479 | static int cap_msg_queue_associate(struct msg_queue *msq, int msqflg) |
480 | { | 480 | { |
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | static int cap_msg_queue_msgctl(struct msg_queue *msq, int cmd) | 484 | static int cap_msg_queue_msgctl(struct msg_queue *msq, int cmd) |
485 | { | 485 | { |
486 | return 0; | 486 | return 0; |
487 | } | 487 | } |
488 | 488 | ||
489 | static int cap_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | 489 | static int cap_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, |
490 | int msgflg) | 490 | int msgflg) |
491 | { | 491 | { |
492 | return 0; | 492 | return 0; |
493 | } | 493 | } |
494 | 494 | ||
495 | static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | 495 | static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, |
496 | struct task_struct *target, long type, int mode) | 496 | struct task_struct *target, long type, int mode) |
497 | { | 497 | { |
498 | return 0; | 498 | return 0; |
499 | } | 499 | } |
500 | 500 | ||
501 | static int cap_shm_alloc_security(struct shmid_kernel *shp) | 501 | static int cap_shm_alloc_security(struct shmid_kernel *shp) |
502 | { | 502 | { |
503 | return 0; | 503 | return 0; |
504 | } | 504 | } |
505 | 505 | ||
506 | static void cap_shm_free_security(struct shmid_kernel *shp) | 506 | static void cap_shm_free_security(struct shmid_kernel *shp) |
507 | { | 507 | { |
508 | } | 508 | } |
509 | 509 | ||
510 | static int cap_shm_associate(struct shmid_kernel *shp, int shmflg) | 510 | static int cap_shm_associate(struct shmid_kernel *shp, int shmflg) |
511 | { | 511 | { |
512 | return 0; | 512 | return 0; |
513 | } | 513 | } |
514 | 514 | ||
515 | static int cap_shm_shmctl(struct shmid_kernel *shp, int cmd) | 515 | static int cap_shm_shmctl(struct shmid_kernel *shp, int cmd) |
516 | { | 516 | { |
517 | return 0; | 517 | return 0; |
518 | } | 518 | } |
519 | 519 | ||
520 | static int cap_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, | 520 | static int cap_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, |
521 | int shmflg) | 521 | int shmflg) |
522 | { | 522 | { |
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | static int cap_sem_alloc_security(struct sem_array *sma) | 526 | static int cap_sem_alloc_security(struct sem_array *sma) |
527 | { | 527 | { |
528 | return 0; | 528 | return 0; |
529 | } | 529 | } |
530 | 530 | ||
531 | static void cap_sem_free_security(struct sem_array *sma) | 531 | static void cap_sem_free_security(struct sem_array *sma) |
532 | { | 532 | { |
533 | } | 533 | } |
534 | 534 | ||
535 | static int cap_sem_associate(struct sem_array *sma, int semflg) | 535 | static int cap_sem_associate(struct sem_array *sma, int semflg) |
536 | { | 536 | { |
537 | return 0; | 537 | return 0; |
538 | } | 538 | } |
539 | 539 | ||
540 | static int cap_sem_semctl(struct sem_array *sma, int cmd) | 540 | static int cap_sem_semctl(struct sem_array *sma, int cmd) |
541 | { | 541 | { |
542 | return 0; | 542 | return 0; |
543 | } | 543 | } |
544 | 544 | ||
545 | static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops, | 545 | static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops, |
546 | unsigned nsops, int alter) | 546 | unsigned nsops, int alter) |
547 | { | 547 | { |
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
551 | #ifdef CONFIG_SECURITY_NETWORK | 551 | #ifdef CONFIG_SECURITY_NETWORK |
552 | static int cap_unix_stream_connect(struct sock *sock, struct sock *other, | 552 | static int cap_unix_stream_connect(struct sock *sock, struct sock *other, |
553 | struct sock *newsk) | 553 | struct sock *newsk) |
554 | { | 554 | { |
555 | return 0; | 555 | return 0; |
556 | } | 556 | } |
557 | 557 | ||
558 | static int cap_unix_may_send(struct socket *sock, struct socket *other) | 558 | static int cap_unix_may_send(struct socket *sock, struct socket *other) |
559 | { | 559 | { |
560 | return 0; | 560 | return 0; |
561 | } | 561 | } |
562 | 562 | ||
563 | static int cap_socket_create(int family, int type, int protocol, int kern) | 563 | static int cap_socket_create(int family, int type, int protocol, int kern) |
564 | { | 564 | { |
565 | return 0; | 565 | return 0; |
566 | } | 566 | } |
567 | 567 | ||
568 | static int cap_socket_post_create(struct socket *sock, int family, int type, | 568 | static int cap_socket_post_create(struct socket *sock, int family, int type, |
569 | int protocol, int kern) | 569 | int protocol, int kern) |
570 | { | 570 | { |
571 | return 0; | 571 | return 0; |
572 | } | 572 | } |
573 | 573 | ||
574 | static int cap_socket_bind(struct socket *sock, struct sockaddr *address, | 574 | static int cap_socket_bind(struct socket *sock, struct sockaddr *address, |
575 | int addrlen) | 575 | int addrlen) |
576 | { | 576 | { |
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | 579 | ||
580 | static int cap_socket_connect(struct socket *sock, struct sockaddr *address, | 580 | static int cap_socket_connect(struct socket *sock, struct sockaddr *address, |
581 | int addrlen) | 581 | int addrlen) |
582 | { | 582 | { |
583 | return 0; | 583 | return 0; |
584 | } | 584 | } |
585 | 585 | ||
586 | static int cap_socket_listen(struct socket *sock, int backlog) | 586 | static int cap_socket_listen(struct socket *sock, int backlog) |
587 | { | 587 | { |
588 | return 0; | 588 | return 0; |
589 | } | 589 | } |
590 | 590 | ||
591 | static int cap_socket_accept(struct socket *sock, struct socket *newsock) | 591 | static int cap_socket_accept(struct socket *sock, struct socket *newsock) |
592 | { | 592 | { |
593 | return 0; | 593 | return 0; |
594 | } | 594 | } |
595 | 595 | ||
596 | static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) | 596 | static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) |
597 | { | 597 | { |
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 601 | static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
602 | int size, int flags) | 602 | int size, int flags) |
603 | { | 603 | { |
604 | return 0; | 604 | return 0; |
605 | } | 605 | } |
606 | 606 | ||
607 | static int cap_socket_getsockname(struct socket *sock) | 607 | static int cap_socket_getsockname(struct socket *sock) |
608 | { | 608 | { |
609 | return 0; | 609 | return 0; |
610 | } | 610 | } |
611 | 611 | ||
612 | static int cap_socket_getpeername(struct socket *sock) | 612 | static int cap_socket_getpeername(struct socket *sock) |
613 | { | 613 | { |
614 | return 0; | 614 | return 0; |
615 | } | 615 | } |
616 | 616 | ||
617 | static int cap_socket_setsockopt(struct socket *sock, int level, int optname) | 617 | static int cap_socket_setsockopt(struct socket *sock, int level, int optname) |
618 | { | 618 | { |
619 | return 0; | 619 | return 0; |
620 | } | 620 | } |
621 | 621 | ||
622 | static int cap_socket_getsockopt(struct socket *sock, int level, int optname) | 622 | static int cap_socket_getsockopt(struct socket *sock, int level, int optname) |
623 | { | 623 | { |
624 | return 0; | 624 | return 0; |
625 | } | 625 | } |
626 | 626 | ||
627 | static int cap_socket_shutdown(struct socket *sock, int how) | 627 | static int cap_socket_shutdown(struct socket *sock, int how) |
628 | { | 628 | { |
629 | return 0; | 629 | return 0; |
630 | } | 630 | } |
631 | 631 | ||
632 | static int cap_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 632 | static int cap_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
633 | { | 633 | { |
634 | return 0; | 634 | return 0; |
635 | } | 635 | } |
636 | 636 | ||
637 | static int cap_socket_getpeersec_stream(struct socket *sock, | 637 | static int cap_socket_getpeersec_stream(struct socket *sock, |
638 | char __user *optval, | 638 | char __user *optval, |
639 | int __user *optlen, unsigned len) | 639 | int __user *optlen, unsigned len) |
640 | { | 640 | { |
641 | return -ENOPROTOOPT; | 641 | return -ENOPROTOOPT; |
642 | } | 642 | } |
643 | 643 | ||
644 | static int cap_socket_getpeersec_dgram(struct socket *sock, | 644 | static int cap_socket_getpeersec_dgram(struct socket *sock, |
645 | struct sk_buff *skb, u32 *secid) | 645 | struct sk_buff *skb, u32 *secid) |
646 | { | 646 | { |
647 | return -ENOPROTOOPT; | 647 | return -ENOPROTOOPT; |
648 | } | 648 | } |
649 | 649 | ||
650 | static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 650 | static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
651 | { | 651 | { |
652 | return 0; | 652 | return 0; |
653 | } | 653 | } |
654 | 654 | ||
655 | static void cap_sk_free_security(struct sock *sk) | 655 | static void cap_sk_free_security(struct sock *sk) |
656 | { | 656 | { |
657 | } | 657 | } |
658 | 658 | ||
659 | static void cap_sk_clone_security(const struct sock *sk, struct sock *newsk) | 659 | static void cap_sk_clone_security(const struct sock *sk, struct sock *newsk) |
660 | { | 660 | { |
661 | } | 661 | } |
662 | 662 | ||
663 | static void cap_sk_getsecid(struct sock *sk, u32 *secid) | 663 | static void cap_sk_getsecid(struct sock *sk, u32 *secid) |
664 | { | 664 | { |
665 | } | 665 | } |
666 | 666 | ||
667 | static void cap_sock_graft(struct sock *sk, struct socket *parent) | 667 | static void cap_sock_graft(struct sock *sk, struct socket *parent) |
668 | { | 668 | { |
669 | } | 669 | } |
670 | 670 | ||
671 | static int cap_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 671 | static int cap_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
672 | struct request_sock *req) | 672 | struct request_sock *req) |
673 | { | 673 | { |
674 | return 0; | 674 | return 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | static void cap_inet_csk_clone(struct sock *newsk, | 677 | static void cap_inet_csk_clone(struct sock *newsk, |
678 | const struct request_sock *req) | 678 | const struct request_sock *req) |
679 | { | 679 | { |
680 | } | 680 | } |
681 | 681 | ||
682 | static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb) | 682 | static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb) |
683 | { | 683 | { |
684 | } | 684 | } |
685 | 685 | ||
686 | static int cap_secmark_relabel_packet(u32 secid) | 686 | static int cap_secmark_relabel_packet(u32 secid) |
687 | { | 687 | { |
688 | return 0; | 688 | return 0; |
689 | } | 689 | } |
690 | 690 | ||
691 | static void cap_secmark_refcount_inc(void) | 691 | static void cap_secmark_refcount_inc(void) |
692 | { | 692 | { |
693 | } | 693 | } |
694 | 694 | ||
695 | static void cap_secmark_refcount_dec(void) | 695 | static void cap_secmark_refcount_dec(void) |
696 | { | 696 | { |
697 | } | 697 | } |
698 | 698 | ||
699 | static void cap_req_classify_flow(const struct request_sock *req, | 699 | static void cap_req_classify_flow(const struct request_sock *req, |
700 | struct flowi *fl) | 700 | struct flowi *fl) |
701 | { | 701 | { |
702 | } | 702 | } |
703 | 703 | ||
704 | static int cap_tun_dev_create(void) | 704 | static int cap_tun_dev_create(void) |
705 | { | 705 | { |
706 | return 0; | 706 | return 0; |
707 | } | 707 | } |
708 | 708 | ||
709 | static void cap_tun_dev_post_create(struct sock *sk) | 709 | static void cap_tun_dev_post_create(struct sock *sk) |
710 | { | 710 | { |
711 | } | 711 | } |
712 | 712 | ||
713 | static int cap_tun_dev_attach(struct sock *sk) | 713 | static int cap_tun_dev_attach(struct sock *sk) |
714 | { | 714 | { |
715 | return 0; | 715 | return 0; |
716 | } | 716 | } |
717 | #endif /* CONFIG_SECURITY_NETWORK */ | 717 | #endif /* CONFIG_SECURITY_NETWORK */ |
718 | 718 | ||
719 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 719 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
720 | static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp, | 720 | static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp, |
721 | struct xfrm_user_sec_ctx *sec_ctx) | 721 | struct xfrm_user_sec_ctx *sec_ctx) |
722 | { | 722 | { |
723 | return 0; | 723 | return 0; |
724 | } | 724 | } |
725 | 725 | ||
726 | static int cap_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx, | 726 | static int cap_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx, |
727 | struct xfrm_sec_ctx **new_ctxp) | 727 | struct xfrm_sec_ctx **new_ctxp) |
728 | { | 728 | { |
729 | return 0; | 729 | return 0; |
730 | } | 730 | } |
731 | 731 | ||
732 | static void cap_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx) | 732 | static void cap_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx) |
733 | { | 733 | { |
734 | } | 734 | } |
735 | 735 | ||
736 | static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx) | 736 | static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx) |
737 | { | 737 | { |
738 | return 0; | 738 | return 0; |
739 | } | 739 | } |
740 | 740 | ||
741 | static int cap_xfrm_state_alloc_security(struct xfrm_state *x, | 741 | static int cap_xfrm_state_alloc_security(struct xfrm_state *x, |
742 | struct xfrm_user_sec_ctx *sec_ctx, | 742 | struct xfrm_user_sec_ctx *sec_ctx, |
743 | u32 secid) | 743 | u32 secid) |
744 | { | 744 | { |
745 | return 0; | 745 | return 0; |
746 | } | 746 | } |
747 | 747 | ||
748 | static void cap_xfrm_state_free_security(struct xfrm_state *x) | 748 | static void cap_xfrm_state_free_security(struct xfrm_state *x) |
749 | { | 749 | { |
750 | } | 750 | } |
751 | 751 | ||
752 | static int cap_xfrm_state_delete_security(struct xfrm_state *x) | 752 | static int cap_xfrm_state_delete_security(struct xfrm_state *x) |
753 | { | 753 | { |
754 | return 0; | 754 | return 0; |
755 | } | 755 | } |
756 | 756 | ||
757 | static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir) | 757 | static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir) |
758 | { | 758 | { |
759 | return 0; | 759 | return 0; |
760 | } | 760 | } |
761 | 761 | ||
762 | static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x, | 762 | static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x, |
763 | struct xfrm_policy *xp, | 763 | struct xfrm_policy *xp, |
764 | const struct flowi *fl) | 764 | const struct flowi *fl) |
765 | { | 765 | { |
766 | return 1; | 766 | return 1; |
767 | } | 767 | } |
768 | 768 | ||
769 | static int cap_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) | 769 | static int cap_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) |
770 | { | 770 | { |
771 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | 773 | ||
774 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 774 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
775 | static void cap_d_instantiate(struct dentry *dentry, struct inode *inode) | 775 | static void cap_d_instantiate(struct dentry *dentry, struct inode *inode) |
776 | { | 776 | { |
777 | } | 777 | } |
778 | 778 | ||
779 | static int cap_getprocattr(struct task_struct *p, char *name, char **value) | 779 | static int cap_getprocattr(struct task_struct *p, char *name, char **value) |
780 | { | 780 | { |
781 | return -EINVAL; | 781 | return -EINVAL; |
782 | } | 782 | } |
783 | 783 | ||
784 | static int cap_setprocattr(struct task_struct *p, char *name, void *value, | 784 | static int cap_setprocattr(struct task_struct *p, char *name, void *value, |
785 | size_t size) | 785 | size_t size) |
786 | { | 786 | { |
787 | return -EINVAL; | 787 | return -EINVAL; |
788 | } | 788 | } |
789 | 789 | ||
790 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 790 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
791 | { | 791 | { |
792 | return -EOPNOTSUPP; | 792 | return -EOPNOTSUPP; |
793 | } | 793 | } |
794 | 794 | ||
795 | static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 795 | static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
796 | { | 796 | { |
797 | *secid = 0; | 797 | *secid = 0; |
798 | return 0; | 798 | return 0; |
799 | } | 799 | } |
800 | 800 | ||
801 | static void cap_release_secctx(char *secdata, u32 seclen) | 801 | static void cap_release_secctx(char *secdata, u32 seclen) |
802 | { | 802 | { |
803 | } | 803 | } |
804 | 804 | ||
805 | static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | 805 | static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) |
806 | { | 806 | { |
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | 809 | ||
810 | static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | 810 | static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) |
811 | { | 811 | { |
812 | return 0; | 812 | return 0; |
813 | } | 813 | } |
814 | 814 | ||
815 | static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | 815 | static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) |
816 | { | 816 | { |
817 | return 0; | 817 | return 0; |
818 | } | 818 | } |
819 | #ifdef CONFIG_KEYS | 819 | #ifdef CONFIG_KEYS |
820 | static int cap_key_alloc(struct key *key, const struct cred *cred, | 820 | static int cap_key_alloc(struct key *key, const struct cred *cred, |
821 | unsigned long flags) | 821 | unsigned long flags) |
822 | { | 822 | { |
823 | return 0; | 823 | return 0; |
824 | } | 824 | } |
825 | 825 | ||
826 | static void cap_key_free(struct key *key) | 826 | static void cap_key_free(struct key *key) |
827 | { | 827 | { |
828 | } | 828 | } |
829 | 829 | ||
830 | static int cap_key_permission(key_ref_t key_ref, const struct cred *cred, | 830 | static int cap_key_permission(key_ref_t key_ref, const struct cred *cred, |
831 | key_perm_t perm) | 831 | key_perm_t perm) |
832 | { | 832 | { |
833 | return 0; | 833 | return 0; |
834 | } | 834 | } |
835 | 835 | ||
836 | static int cap_key_getsecurity(struct key *key, char **_buffer) | 836 | static int cap_key_getsecurity(struct key *key, char **_buffer) |
837 | { | 837 | { |
838 | *_buffer = NULL; | 838 | *_buffer = NULL; |
839 | return 0; | 839 | return 0; |
840 | } | 840 | } |
841 | 841 | ||
842 | #endif /* CONFIG_KEYS */ | 842 | #endif /* CONFIG_KEYS */ |
843 | 843 | ||
844 | #ifdef CONFIG_AUDIT | 844 | #ifdef CONFIG_AUDIT |
845 | static int cap_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) | 845 | static int cap_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) |
846 | { | 846 | { |
847 | return 0; | 847 | return 0; |
848 | } | 848 | } |
849 | 849 | ||
850 | static int cap_audit_rule_known(struct audit_krule *krule) | 850 | static int cap_audit_rule_known(struct audit_krule *krule) |
851 | { | 851 | { |
852 | return 0; | 852 | return 0; |
853 | } | 853 | } |
854 | 854 | ||
855 | static int cap_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, | 855 | static int cap_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, |
856 | struct audit_context *actx) | 856 | struct audit_context *actx) |
857 | { | 857 | { |
858 | return 0; | 858 | return 0; |
859 | } | 859 | } |
860 | 860 | ||
861 | static void cap_audit_rule_free(void *lsmrule) | 861 | static void cap_audit_rule_free(void *lsmrule) |
862 | { | 862 | { |
863 | } | 863 | } |
864 | #endif /* CONFIG_AUDIT */ | 864 | #endif /* CONFIG_AUDIT */ |
865 | 865 | ||
866 | #define set_to_cap_if_null(ops, function) \ | 866 | #define set_to_cap_if_null(ops, function) \ |
867 | do { \ | 867 | do { \ |
868 | if (!ops->function) { \ | 868 | if (!ops->function) { \ |
869 | ops->function = cap_##function; \ | 869 | ops->function = cap_##function; \ |
870 | pr_debug("Had to override the " #function \ | 870 | pr_debug("Had to override the " #function \ |
871 | " security operation with the default.\n");\ | 871 | " security operation with the default.\n");\ |
872 | } \ | 872 | } \ |
873 | } while (0) | 873 | } while (0) |
874 | 874 | ||
875 | void __init security_fixup_ops(struct security_operations *ops) | 875 | void __init security_fixup_ops(struct security_operations *ops) |
876 | { | 876 | { |
877 | set_to_cap_if_null(ops, ptrace_access_check); | 877 | set_to_cap_if_null(ops, ptrace_access_check); |
878 | set_to_cap_if_null(ops, ptrace_traceme); | 878 | set_to_cap_if_null(ops, ptrace_traceme); |
879 | set_to_cap_if_null(ops, capget); | 879 | set_to_cap_if_null(ops, capget); |
880 | set_to_cap_if_null(ops, capset); | 880 | set_to_cap_if_null(ops, capset); |
881 | set_to_cap_if_null(ops, capable); | 881 | set_to_cap_if_null(ops, capable); |
882 | set_to_cap_if_null(ops, quotactl); | 882 | set_to_cap_if_null(ops, quotactl); |
883 | set_to_cap_if_null(ops, quota_on); | 883 | set_to_cap_if_null(ops, quota_on); |
884 | set_to_cap_if_null(ops, syslog); | 884 | set_to_cap_if_null(ops, syslog); |
885 | set_to_cap_if_null(ops, settime); | 885 | set_to_cap_if_null(ops, settime); |
886 | set_to_cap_if_null(ops, vm_enough_memory); | 886 | set_to_cap_if_null(ops, vm_enough_memory); |
887 | set_to_cap_if_null(ops, bprm_set_creds); | 887 | set_to_cap_if_null(ops, bprm_set_creds); |
888 | set_to_cap_if_null(ops, bprm_committing_creds); | 888 | set_to_cap_if_null(ops, bprm_committing_creds); |
889 | set_to_cap_if_null(ops, bprm_committed_creds); | 889 | set_to_cap_if_null(ops, bprm_committed_creds); |
890 | set_to_cap_if_null(ops, bprm_check_security); | 890 | set_to_cap_if_null(ops, bprm_check_security); |
891 | set_to_cap_if_null(ops, bprm_secureexec); | 891 | set_to_cap_if_null(ops, bprm_secureexec); |
892 | set_to_cap_if_null(ops, sb_alloc_security); | 892 | set_to_cap_if_null(ops, sb_alloc_security); |
893 | set_to_cap_if_null(ops, sb_free_security); | 893 | set_to_cap_if_null(ops, sb_free_security); |
894 | set_to_cap_if_null(ops, sb_copy_data); | 894 | set_to_cap_if_null(ops, sb_copy_data); |
895 | set_to_cap_if_null(ops, sb_remount); | 895 | set_to_cap_if_null(ops, sb_remount); |
896 | set_to_cap_if_null(ops, sb_kern_mount); | 896 | set_to_cap_if_null(ops, sb_kern_mount); |
897 | set_to_cap_if_null(ops, sb_show_options); | 897 | set_to_cap_if_null(ops, sb_show_options); |
898 | set_to_cap_if_null(ops, sb_statfs); | 898 | set_to_cap_if_null(ops, sb_statfs); |
899 | set_to_cap_if_null(ops, sb_mount); | 899 | set_to_cap_if_null(ops, sb_mount); |
900 | set_to_cap_if_null(ops, sb_umount); | 900 | set_to_cap_if_null(ops, sb_umount); |
901 | set_to_cap_if_null(ops, sb_pivotroot); | 901 | set_to_cap_if_null(ops, sb_pivotroot); |
902 | set_to_cap_if_null(ops, sb_set_mnt_opts); | 902 | set_to_cap_if_null(ops, sb_set_mnt_opts); |
903 | set_to_cap_if_null(ops, sb_clone_mnt_opts); | 903 | set_to_cap_if_null(ops, sb_clone_mnt_opts); |
904 | set_to_cap_if_null(ops, sb_parse_opts_str); | 904 | set_to_cap_if_null(ops, sb_parse_opts_str); |
905 | set_to_cap_if_null(ops, inode_alloc_security); | 905 | set_to_cap_if_null(ops, inode_alloc_security); |
906 | set_to_cap_if_null(ops, inode_free_security); | 906 | set_to_cap_if_null(ops, inode_free_security); |
907 | set_to_cap_if_null(ops, inode_init_security); | 907 | set_to_cap_if_null(ops, inode_init_security); |
908 | set_to_cap_if_null(ops, inode_create); | 908 | set_to_cap_if_null(ops, inode_create); |
909 | set_to_cap_if_null(ops, inode_link); | 909 | set_to_cap_if_null(ops, inode_link); |
910 | set_to_cap_if_null(ops, inode_unlink); | 910 | set_to_cap_if_null(ops, inode_unlink); |
911 | set_to_cap_if_null(ops, inode_symlink); | 911 | set_to_cap_if_null(ops, inode_symlink); |
912 | set_to_cap_if_null(ops, inode_mkdir); | 912 | set_to_cap_if_null(ops, inode_mkdir); |
913 | set_to_cap_if_null(ops, inode_rmdir); | 913 | set_to_cap_if_null(ops, inode_rmdir); |
914 | set_to_cap_if_null(ops, inode_mknod); | 914 | set_to_cap_if_null(ops, inode_mknod); |
915 | set_to_cap_if_null(ops, inode_rename); | 915 | set_to_cap_if_null(ops, inode_rename); |
916 | set_to_cap_if_null(ops, inode_readlink); | 916 | set_to_cap_if_null(ops, inode_readlink); |
917 | set_to_cap_if_null(ops, inode_follow_link); | 917 | set_to_cap_if_null(ops, inode_follow_link); |
918 | set_to_cap_if_null(ops, inode_permission); | 918 | set_to_cap_if_null(ops, inode_permission); |
919 | set_to_cap_if_null(ops, inode_setattr); | 919 | set_to_cap_if_null(ops, inode_setattr); |
920 | set_to_cap_if_null(ops, inode_getattr); | 920 | set_to_cap_if_null(ops, inode_getattr); |
921 | set_to_cap_if_null(ops, inode_setxattr); | 921 | set_to_cap_if_null(ops, inode_setxattr); |
922 | set_to_cap_if_null(ops, inode_post_setxattr); | 922 | set_to_cap_if_null(ops, inode_post_setxattr); |
923 | set_to_cap_if_null(ops, inode_getxattr); | 923 | set_to_cap_if_null(ops, inode_getxattr); |
924 | set_to_cap_if_null(ops, inode_listxattr); | 924 | set_to_cap_if_null(ops, inode_listxattr); |
925 | set_to_cap_if_null(ops, inode_removexattr); | 925 | set_to_cap_if_null(ops, inode_removexattr); |
926 | set_to_cap_if_null(ops, inode_need_killpriv); | 926 | set_to_cap_if_null(ops, inode_need_killpriv); |
927 | set_to_cap_if_null(ops, inode_killpriv); | 927 | set_to_cap_if_null(ops, inode_killpriv); |
928 | set_to_cap_if_null(ops, inode_getsecurity); | 928 | set_to_cap_if_null(ops, inode_getsecurity); |
929 | set_to_cap_if_null(ops, inode_setsecurity); | 929 | set_to_cap_if_null(ops, inode_setsecurity); |
930 | set_to_cap_if_null(ops, inode_listsecurity); | 930 | set_to_cap_if_null(ops, inode_listsecurity); |
931 | set_to_cap_if_null(ops, inode_getsecid); | 931 | set_to_cap_if_null(ops, inode_getsecid); |
932 | #ifdef CONFIG_SECURITY_PATH | 932 | #ifdef CONFIG_SECURITY_PATH |
933 | set_to_cap_if_null(ops, path_mknod); | 933 | set_to_cap_if_null(ops, path_mknod); |
934 | set_to_cap_if_null(ops, path_mkdir); | 934 | set_to_cap_if_null(ops, path_mkdir); |
935 | set_to_cap_if_null(ops, path_rmdir); | 935 | set_to_cap_if_null(ops, path_rmdir); |
936 | set_to_cap_if_null(ops, path_unlink); | 936 | set_to_cap_if_null(ops, path_unlink); |
937 | set_to_cap_if_null(ops, path_symlink); | 937 | set_to_cap_if_null(ops, path_symlink); |
938 | set_to_cap_if_null(ops, path_link); | 938 | set_to_cap_if_null(ops, path_link); |
939 | set_to_cap_if_null(ops, path_rename); | 939 | set_to_cap_if_null(ops, path_rename); |
940 | set_to_cap_if_null(ops, path_truncate); | 940 | set_to_cap_if_null(ops, path_truncate); |
941 | set_to_cap_if_null(ops, path_chmod); | 941 | set_to_cap_if_null(ops, path_chmod); |
942 | set_to_cap_if_null(ops, path_chown); | 942 | set_to_cap_if_null(ops, path_chown); |
943 | set_to_cap_if_null(ops, path_chroot); | 943 | set_to_cap_if_null(ops, path_chroot); |
944 | #endif | 944 | #endif |
945 | set_to_cap_if_null(ops, file_permission); | 945 | set_to_cap_if_null(ops, file_permission); |
946 | set_to_cap_if_null(ops, file_alloc_security); | 946 | set_to_cap_if_null(ops, file_alloc_security); |
947 | set_to_cap_if_null(ops, file_free_security); | 947 | set_to_cap_if_null(ops, file_free_security); |
948 | set_to_cap_if_null(ops, file_ioctl); | 948 | set_to_cap_if_null(ops, file_ioctl); |
949 | set_to_cap_if_null(ops, file_mmap); | 949 | set_to_cap_if_null(ops, file_mmap); |
950 | set_to_cap_if_null(ops, file_mprotect); | 950 | set_to_cap_if_null(ops, file_mprotect); |
951 | set_to_cap_if_null(ops, file_lock); | 951 | set_to_cap_if_null(ops, file_lock); |
952 | set_to_cap_if_null(ops, file_fcntl); | 952 | set_to_cap_if_null(ops, file_fcntl); |
953 | set_to_cap_if_null(ops, file_set_fowner); | 953 | set_to_cap_if_null(ops, file_set_fowner); |
954 | set_to_cap_if_null(ops, file_send_sigiotask); | 954 | set_to_cap_if_null(ops, file_send_sigiotask); |
955 | set_to_cap_if_null(ops, file_receive); | 955 | set_to_cap_if_null(ops, file_receive); |
956 | set_to_cap_if_null(ops, dentry_open); | 956 | set_to_cap_if_null(ops, dentry_open); |
957 | set_to_cap_if_null(ops, task_create); | 957 | set_to_cap_if_null(ops, task_create); |
958 | set_to_cap_if_null(ops, cred_alloc_blank); | 958 | set_to_cap_if_null(ops, cred_alloc_blank); |
959 | set_to_cap_if_null(ops, cred_free); | 959 | set_to_cap_if_null(ops, cred_free); |
960 | set_to_cap_if_null(ops, cred_prepare); | 960 | set_to_cap_if_null(ops, cred_prepare); |
961 | set_to_cap_if_null(ops, cred_transfer); | 961 | set_to_cap_if_null(ops, cred_transfer); |
962 | set_to_cap_if_null(ops, kernel_act_as); | 962 | set_to_cap_if_null(ops, kernel_act_as); |
963 | set_to_cap_if_null(ops, kernel_create_files_as); | 963 | set_to_cap_if_null(ops, kernel_create_files_as); |
964 | set_to_cap_if_null(ops, kernel_module_request); | 964 | set_to_cap_if_null(ops, kernel_module_request); |
965 | set_to_cap_if_null(ops, task_fix_setuid); | 965 | set_to_cap_if_null(ops, task_fix_setuid); |
966 | set_to_cap_if_null(ops, task_setpgid); | 966 | set_to_cap_if_null(ops, task_setpgid); |
967 | set_to_cap_if_null(ops, task_getpgid); | 967 | set_to_cap_if_null(ops, task_getpgid); |
968 | set_to_cap_if_null(ops, task_getsid); | 968 | set_to_cap_if_null(ops, task_getsid); |
969 | set_to_cap_if_null(ops, task_getsecid); | 969 | set_to_cap_if_null(ops, task_getsecid); |
970 | set_to_cap_if_null(ops, task_setnice); | 970 | set_to_cap_if_null(ops, task_setnice); |
971 | set_to_cap_if_null(ops, task_setioprio); | 971 | set_to_cap_if_null(ops, task_setioprio); |
972 | set_to_cap_if_null(ops, task_getioprio); | 972 | set_to_cap_if_null(ops, task_getioprio); |
973 | set_to_cap_if_null(ops, task_setrlimit); | 973 | set_to_cap_if_null(ops, task_setrlimit); |
974 | set_to_cap_if_null(ops, task_setscheduler); | 974 | set_to_cap_if_null(ops, task_setscheduler); |
975 | set_to_cap_if_null(ops, task_getscheduler); | 975 | set_to_cap_if_null(ops, task_getscheduler); |
976 | set_to_cap_if_null(ops, task_movememory); | 976 | set_to_cap_if_null(ops, task_movememory); |
977 | set_to_cap_if_null(ops, task_wait); | 977 | set_to_cap_if_null(ops, task_wait); |
978 | set_to_cap_if_null(ops, task_kill); | 978 | set_to_cap_if_null(ops, task_kill); |
979 | set_to_cap_if_null(ops, task_prctl); | 979 | set_to_cap_if_null(ops, task_prctl); |
980 | set_to_cap_if_null(ops, task_to_inode); | 980 | set_to_cap_if_null(ops, task_to_inode); |
981 | set_to_cap_if_null(ops, ipc_permission); | 981 | set_to_cap_if_null(ops, ipc_permission); |
982 | set_to_cap_if_null(ops, ipc_getsecid); | 982 | set_to_cap_if_null(ops, ipc_getsecid); |
983 | set_to_cap_if_null(ops, msg_msg_alloc_security); | 983 | set_to_cap_if_null(ops, msg_msg_alloc_security); |
984 | set_to_cap_if_null(ops, msg_msg_free_security); | 984 | set_to_cap_if_null(ops, msg_msg_free_security); |
985 | set_to_cap_if_null(ops, msg_queue_alloc_security); | 985 | set_to_cap_if_null(ops, msg_queue_alloc_security); |
986 | set_to_cap_if_null(ops, msg_queue_free_security); | 986 | set_to_cap_if_null(ops, msg_queue_free_security); |
987 | set_to_cap_if_null(ops, msg_queue_associate); | 987 | set_to_cap_if_null(ops, msg_queue_associate); |
988 | set_to_cap_if_null(ops, msg_queue_msgctl); | 988 | set_to_cap_if_null(ops, msg_queue_msgctl); |
989 | set_to_cap_if_null(ops, msg_queue_msgsnd); | 989 | set_to_cap_if_null(ops, msg_queue_msgsnd); |
990 | set_to_cap_if_null(ops, msg_queue_msgrcv); | 990 | set_to_cap_if_null(ops, msg_queue_msgrcv); |
991 | set_to_cap_if_null(ops, shm_alloc_security); | 991 | set_to_cap_if_null(ops, shm_alloc_security); |
992 | set_to_cap_if_null(ops, shm_free_security); | 992 | set_to_cap_if_null(ops, shm_free_security); |
993 | set_to_cap_if_null(ops, shm_associate); | 993 | set_to_cap_if_null(ops, shm_associate); |
994 | set_to_cap_if_null(ops, shm_shmctl); | 994 | set_to_cap_if_null(ops, shm_shmctl); |
995 | set_to_cap_if_null(ops, shm_shmat); | 995 | set_to_cap_if_null(ops, shm_shmat); |
996 | set_to_cap_if_null(ops, sem_alloc_security); | 996 | set_to_cap_if_null(ops, sem_alloc_security); |
997 | set_to_cap_if_null(ops, sem_free_security); | 997 | set_to_cap_if_null(ops, sem_free_security); |
998 | set_to_cap_if_null(ops, sem_associate); | 998 | set_to_cap_if_null(ops, sem_associate); |
999 | set_to_cap_if_null(ops, sem_semctl); | 999 | set_to_cap_if_null(ops, sem_semctl); |
1000 | set_to_cap_if_null(ops, sem_semop); | 1000 | set_to_cap_if_null(ops, sem_semop); |
1001 | set_to_cap_if_null(ops, netlink_send); | 1001 | set_to_cap_if_null(ops, netlink_send); |
1002 | set_to_cap_if_null(ops, netlink_recv); | ||
1003 | set_to_cap_if_null(ops, d_instantiate); | 1002 | set_to_cap_if_null(ops, d_instantiate); |
1004 | set_to_cap_if_null(ops, getprocattr); | 1003 | set_to_cap_if_null(ops, getprocattr); |
1005 | set_to_cap_if_null(ops, setprocattr); | 1004 | set_to_cap_if_null(ops, setprocattr); |
1006 | set_to_cap_if_null(ops, secid_to_secctx); | 1005 | set_to_cap_if_null(ops, secid_to_secctx); |
1007 | set_to_cap_if_null(ops, secctx_to_secid); | 1006 | set_to_cap_if_null(ops, secctx_to_secid); |
1008 | set_to_cap_if_null(ops, release_secctx); | 1007 | set_to_cap_if_null(ops, release_secctx); |
1009 | set_to_cap_if_null(ops, inode_notifysecctx); | 1008 | set_to_cap_if_null(ops, inode_notifysecctx); |
1010 | set_to_cap_if_null(ops, inode_setsecctx); | 1009 | set_to_cap_if_null(ops, inode_setsecctx); |
1011 | set_to_cap_if_null(ops, inode_getsecctx); | 1010 | set_to_cap_if_null(ops, inode_getsecctx); |
1012 | #ifdef CONFIG_SECURITY_NETWORK | 1011 | #ifdef CONFIG_SECURITY_NETWORK |
1013 | set_to_cap_if_null(ops, unix_stream_connect); | 1012 | set_to_cap_if_null(ops, unix_stream_connect); |
1014 | set_to_cap_if_null(ops, unix_may_send); | 1013 | set_to_cap_if_null(ops, unix_may_send); |
1015 | set_to_cap_if_null(ops, socket_create); | 1014 | set_to_cap_if_null(ops, socket_create); |
1016 | set_to_cap_if_null(ops, socket_post_create); | 1015 | set_to_cap_if_null(ops, socket_post_create); |
1017 | set_to_cap_if_null(ops, socket_bind); | 1016 | set_to_cap_if_null(ops, socket_bind); |
1018 | set_to_cap_if_null(ops, socket_connect); | 1017 | set_to_cap_if_null(ops, socket_connect); |
1019 | set_to_cap_if_null(ops, socket_listen); | 1018 | set_to_cap_if_null(ops, socket_listen); |
1020 | set_to_cap_if_null(ops, socket_accept); | 1019 | set_to_cap_if_null(ops, socket_accept); |
1021 | set_to_cap_if_null(ops, socket_sendmsg); | 1020 | set_to_cap_if_null(ops, socket_sendmsg); |
1022 | set_to_cap_if_null(ops, socket_recvmsg); | 1021 | set_to_cap_if_null(ops, socket_recvmsg); |
1023 | set_to_cap_if_null(ops, socket_getsockname); | 1022 | set_to_cap_if_null(ops, socket_getsockname); |
1024 | set_to_cap_if_null(ops, socket_getpeername); | 1023 | set_to_cap_if_null(ops, socket_getpeername); |
1025 | set_to_cap_if_null(ops, socket_setsockopt); | 1024 | set_to_cap_if_null(ops, socket_setsockopt); |
1026 | set_to_cap_if_null(ops, socket_getsockopt); | 1025 | set_to_cap_if_null(ops, socket_getsockopt); |
1027 | set_to_cap_if_null(ops, socket_shutdown); | 1026 | set_to_cap_if_null(ops, socket_shutdown); |
1028 | set_to_cap_if_null(ops, socket_sock_rcv_skb); | 1027 | set_to_cap_if_null(ops, socket_sock_rcv_skb); |
1029 | set_to_cap_if_null(ops, socket_getpeersec_stream); | 1028 | set_to_cap_if_null(ops, socket_getpeersec_stream); |
1030 | set_to_cap_if_null(ops, socket_getpeersec_dgram); | 1029 | set_to_cap_if_null(ops, socket_getpeersec_dgram); |
1031 | set_to_cap_if_null(ops, sk_alloc_security); | 1030 | set_to_cap_if_null(ops, sk_alloc_security); |
1032 | set_to_cap_if_null(ops, sk_free_security); | 1031 | set_to_cap_if_null(ops, sk_free_security); |
1033 | set_to_cap_if_null(ops, sk_clone_security); | 1032 | set_to_cap_if_null(ops, sk_clone_security); |
1034 | set_to_cap_if_null(ops, sk_getsecid); | 1033 | set_to_cap_if_null(ops, sk_getsecid); |
1035 | set_to_cap_if_null(ops, sock_graft); | 1034 | set_to_cap_if_null(ops, sock_graft); |
1036 | set_to_cap_if_null(ops, inet_conn_request); | 1035 | set_to_cap_if_null(ops, inet_conn_request); |
1037 | set_to_cap_if_null(ops, inet_csk_clone); | 1036 | set_to_cap_if_null(ops, inet_csk_clone); |
1038 | set_to_cap_if_null(ops, inet_conn_established); | 1037 | set_to_cap_if_null(ops, inet_conn_established); |
1039 | set_to_cap_if_null(ops, secmark_relabel_packet); | 1038 | set_to_cap_if_null(ops, secmark_relabel_packet); |
1040 | set_to_cap_if_null(ops, secmark_refcount_inc); | 1039 | set_to_cap_if_null(ops, secmark_refcount_inc); |
1041 | set_to_cap_if_null(ops, secmark_refcount_dec); | 1040 | set_to_cap_if_null(ops, secmark_refcount_dec); |
1042 | set_to_cap_if_null(ops, req_classify_flow); | 1041 | set_to_cap_if_null(ops, req_classify_flow); |
1043 | set_to_cap_if_null(ops, tun_dev_create); | 1042 | set_to_cap_if_null(ops, tun_dev_create); |
1044 | set_to_cap_if_null(ops, tun_dev_post_create); | 1043 | set_to_cap_if_null(ops, tun_dev_post_create); |
1045 | set_to_cap_if_null(ops, tun_dev_attach); | 1044 | set_to_cap_if_null(ops, tun_dev_attach); |
1046 | #endif /* CONFIG_SECURITY_NETWORK */ | 1045 | #endif /* CONFIG_SECURITY_NETWORK */ |
1047 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1046 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1048 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); | 1047 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); |
1049 | set_to_cap_if_null(ops, xfrm_policy_clone_security); | 1048 | set_to_cap_if_null(ops, xfrm_policy_clone_security); |
1050 | set_to_cap_if_null(ops, xfrm_policy_free_security); | 1049 | set_to_cap_if_null(ops, xfrm_policy_free_security); |
1051 | set_to_cap_if_null(ops, xfrm_policy_delete_security); | 1050 | set_to_cap_if_null(ops, xfrm_policy_delete_security); |
1052 | set_to_cap_if_null(ops, xfrm_state_alloc_security); | 1051 | set_to_cap_if_null(ops, xfrm_state_alloc_security); |
1053 | set_to_cap_if_null(ops, xfrm_state_free_security); | 1052 | set_to_cap_if_null(ops, xfrm_state_free_security); |
1054 | set_to_cap_if_null(ops, xfrm_state_delete_security); | 1053 | set_to_cap_if_null(ops, xfrm_state_delete_security); |
1055 | set_to_cap_if_null(ops, xfrm_policy_lookup); | 1054 | set_to_cap_if_null(ops, xfrm_policy_lookup); |
1056 | set_to_cap_if_null(ops, xfrm_state_pol_flow_match); | 1055 | set_to_cap_if_null(ops, xfrm_state_pol_flow_match); |
1057 | set_to_cap_if_null(ops, xfrm_decode_session); | 1056 | set_to_cap_if_null(ops, xfrm_decode_session); |
1058 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 1057 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
1059 | #ifdef CONFIG_KEYS | 1058 | #ifdef CONFIG_KEYS |
1060 | set_to_cap_if_null(ops, key_alloc); | 1059 | set_to_cap_if_null(ops, key_alloc); |
1061 | set_to_cap_if_null(ops, key_free); | 1060 | set_to_cap_if_null(ops, key_free); |
1062 | set_to_cap_if_null(ops, key_permission); | 1061 | set_to_cap_if_null(ops, key_permission); |
1063 | set_to_cap_if_null(ops, key_getsecurity); | 1062 | set_to_cap_if_null(ops, key_getsecurity); |
1064 | #endif /* CONFIG_KEYS */ | 1063 | #endif /* CONFIG_KEYS */ |
1065 | #ifdef CONFIG_AUDIT | 1064 | #ifdef CONFIG_AUDIT |
1066 | set_to_cap_if_null(ops, audit_rule_init); | 1065 | set_to_cap_if_null(ops, audit_rule_init); |
1067 | set_to_cap_if_null(ops, audit_rule_known); | 1066 | set_to_cap_if_null(ops, audit_rule_known); |
1068 | set_to_cap_if_null(ops, audit_rule_match); | 1067 | set_to_cap_if_null(ops, audit_rule_match); |
1069 | set_to_cap_if_null(ops, audit_rule_free); | 1068 | set_to_cap_if_null(ops, audit_rule_free); |
1070 | #endif | 1069 | #endif |
1071 | } | 1070 | } |
1072 | 1071 |
security/commoncap.c
1 | /* Common capabilities, needed by capability.o. | 1 | /* Common capabilities, needed by capability.o. |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | 3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by | 4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or | 5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. | 6 | * (at your option) any later version. |
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
11 | #include <linux/audit.h> | 11 | #include <linux/audit.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/security.h> | 15 | #include <linux/security.h> |
16 | #include <linux/file.h> | 16 | #include <linux/file.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/mman.h> | 18 | #include <linux/mman.h> |
19 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
20 | #include <linux/swap.h> | 20 | #include <linux/swap.h> |
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/netlink.h> | 22 | #include <linux/netlink.h> |
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/xattr.h> | 24 | #include <linux/xattr.h> |
25 | #include <linux/hugetlb.h> | 25 | #include <linux/hugetlb.h> |
26 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/prctl.h> | 28 | #include <linux/prctl.h> |
29 | #include <linux/securebits.h> | 29 | #include <linux/securebits.h> |
30 | #include <linux/user_namespace.h> | 30 | #include <linux/user_namespace.h> |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * If a non-root user executes a setuid-root binary in | 33 | * If a non-root user executes a setuid-root binary in |
34 | * !secure(SECURE_NOROOT) mode, then we raise capabilities. | 34 | * !secure(SECURE_NOROOT) mode, then we raise capabilities. |
35 | * However if fE is also set, then the intent is for only | 35 | * However if fE is also set, then the intent is for only |
36 | * the file capabilities to be applied, and the setuid-root | 36 | * the file capabilities to be applied, and the setuid-root |
37 | * bit is left on either to change the uid (plausible) or | 37 | * bit is left on either to change the uid (plausible) or |
38 | * to get full privilege on a kernel without file capabilities | 38 | * to get full privilege on a kernel without file capabilities |
39 | * support. So in that case we do not raise capabilities. | 39 | * support. So in that case we do not raise capabilities. |
40 | * | 40 | * |
41 | * Warn if that happens, once per boot. | 41 | * Warn if that happens, once per boot. |
42 | */ | 42 | */ |
43 | static void warn_setuid_and_fcaps_mixed(const char *fname) | 43 | static void warn_setuid_and_fcaps_mixed(const char *fname) |
44 | { | 44 | { |
45 | static int warned; | 45 | static int warned; |
46 | if (!warned) { | 46 | if (!warned) { |
47 | printk(KERN_INFO "warning: `%s' has both setuid-root and" | 47 | printk(KERN_INFO "warning: `%s' has both setuid-root and" |
48 | " effective capabilities. Therefore not raising all" | 48 | " effective capabilities. Therefore not raising all" |
49 | " capabilities.\n", fname); | 49 | " capabilities.\n", fname); |
50 | warned = 1; | 50 | warned = 1; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) | 54 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) |
55 | { | 55 | { |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | int cap_netlink_recv(struct sk_buff *skb, int cap) | ||
60 | { | ||
61 | if (!cap_raised(current_cap(), cap)) | ||
62 | return -EPERM; | ||
63 | return 0; | ||
64 | } | ||
65 | EXPORT_SYMBOL(cap_netlink_recv); | ||
66 | |||
67 | /** | 59 | /** |
68 | * cap_capable - Determine whether a task has a particular effective capability | 60 | * cap_capable - Determine whether a task has a particular effective capability |
69 | * @cred: The credentials to use | 61 | * @cred: The credentials to use |
70 | * @ns: The user namespace in which we need the capability | 62 | * @ns: The user namespace in which we need the capability |
71 | * @cap: The capability to check for | 63 | * @cap: The capability to check for |
72 | * @audit: Whether to write an audit message or not | 64 | * @audit: Whether to write an audit message or not |
73 | * | 65 | * |
74 | * Determine whether the nominated task has the specified capability amongst | 66 | * Determine whether the nominated task has the specified capability amongst |
75 | * its effective set, returning 0 if it does, -ve if it does not. | 67 | * its effective set, returning 0 if it does, -ve if it does not. |
76 | * | 68 | * |
77 | * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable() | 69 | * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable() |
78 | * and has_capability() functions. That is, it has the reverse semantics: | 70 | * and has_capability() functions. That is, it has the reverse semantics: |
79 | * cap_has_capability() returns 0 when a task has a capability, but the | 71 | * cap_has_capability() returns 0 when a task has a capability, but the |
80 | * kernel's capable() and has_capability() returns 1 for this case. | 72 | * kernel's capable() and has_capability() returns 1 for this case. |
81 | */ | 73 | */ |
82 | int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | 74 | int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, |
83 | int cap, int audit) | 75 | int cap, int audit) |
84 | { | 76 | { |
85 | for (;;) { | 77 | for (;;) { |
86 | /* The creator of the user namespace has all caps. */ | 78 | /* The creator of the user namespace has all caps. */ |
87 | if (targ_ns != &init_user_ns && targ_ns->creator == cred->user) | 79 | if (targ_ns != &init_user_ns && targ_ns->creator == cred->user) |
88 | return 0; | 80 | return 0; |
89 | 81 | ||
90 | /* Do we have the necessary capabilities? */ | 82 | /* Do we have the necessary capabilities? */ |
91 | if (targ_ns == cred->user->user_ns) | 83 | if (targ_ns == cred->user->user_ns) |
92 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; | 84 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; |
93 | 85 | ||
94 | /* Have we tried all of the parent namespaces? */ | 86 | /* Have we tried all of the parent namespaces? */ |
95 | if (targ_ns == &init_user_ns) | 87 | if (targ_ns == &init_user_ns) |
96 | return -EPERM; | 88 | return -EPERM; |
97 | 89 | ||
98 | /* | 90 | /* |
99 | *If you have a capability in a parent user ns, then you have | 91 | *If you have a capability in a parent user ns, then you have |
100 | * it over all children user namespaces as well. | 92 | * it over all children user namespaces as well. |
101 | */ | 93 | */ |
102 | targ_ns = targ_ns->creator->user_ns; | 94 | targ_ns = targ_ns->creator->user_ns; |
103 | } | 95 | } |
104 | 96 | ||
105 | /* We never get here */ | 97 | /* We never get here */ |
106 | } | 98 | } |
107 | 99 | ||
108 | /** | 100 | /** |
109 | * cap_settime - Determine whether the current process may set the system clock | 101 | * cap_settime - Determine whether the current process may set the system clock |
110 | * @ts: The time to set | 102 | * @ts: The time to set |
111 | * @tz: The timezone to set | 103 | * @tz: The timezone to set |
112 | * | 104 | * |
113 | * Determine whether the current process may set the system clock and timezone | 105 | * Determine whether the current process may set the system clock and timezone |
114 | * information, returning 0 if permission granted, -ve if denied. | 106 | * information, returning 0 if permission granted, -ve if denied. |
115 | */ | 107 | */ |
116 | int cap_settime(const struct timespec *ts, const struct timezone *tz) | 108 | int cap_settime(const struct timespec *ts, const struct timezone *tz) |
117 | { | 109 | { |
118 | if (!capable(CAP_SYS_TIME)) | 110 | if (!capable(CAP_SYS_TIME)) |
119 | return -EPERM; | 111 | return -EPERM; |
120 | return 0; | 112 | return 0; |
121 | } | 113 | } |
122 | 114 | ||
123 | /** | 115 | /** |
124 | * cap_ptrace_access_check - Determine whether the current process may access | 116 | * cap_ptrace_access_check - Determine whether the current process may access |
125 | * another | 117 | * another |
126 | * @child: The process to be accessed | 118 | * @child: The process to be accessed |
127 | * @mode: The mode of attachment. | 119 | * @mode: The mode of attachment. |
128 | * | 120 | * |
129 | * If we are in the same or an ancestor user_ns and have all the target | 121 | * If we are in the same or an ancestor user_ns and have all the target |
130 | * task's capabilities, then ptrace access is allowed. | 122 | * task's capabilities, then ptrace access is allowed. |
131 | * If we have the ptrace capability to the target user_ns, then ptrace | 123 | * If we have the ptrace capability to the target user_ns, then ptrace |
132 | * access is allowed. | 124 | * access is allowed. |
133 | * Else denied. | 125 | * Else denied. |
134 | * | 126 | * |
135 | * Determine whether a process may access another, returning 0 if permission | 127 | * Determine whether a process may access another, returning 0 if permission |
136 | * granted, -ve if denied. | 128 | * granted, -ve if denied. |
137 | */ | 129 | */ |
138 | int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) | 130 | int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) |
139 | { | 131 | { |
140 | int ret = 0; | 132 | int ret = 0; |
141 | const struct cred *cred, *child_cred; | 133 | const struct cred *cred, *child_cred; |
142 | 134 | ||
143 | rcu_read_lock(); | 135 | rcu_read_lock(); |
144 | cred = current_cred(); | 136 | cred = current_cred(); |
145 | child_cred = __task_cred(child); | 137 | child_cred = __task_cred(child); |
146 | if (cred->user->user_ns == child_cred->user->user_ns && | 138 | if (cred->user->user_ns == child_cred->user->user_ns && |
147 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 139 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
148 | goto out; | 140 | goto out; |
149 | if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) | 141 | if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) |
150 | goto out; | 142 | goto out; |
151 | ret = -EPERM; | 143 | ret = -EPERM; |
152 | out: | 144 | out: |
153 | rcu_read_unlock(); | 145 | rcu_read_unlock(); |
154 | return ret; | 146 | return ret; |
155 | } | 147 | } |
156 | 148 | ||
157 | /** | 149 | /** |
158 | * cap_ptrace_traceme - Determine whether another process may trace the current | 150 | * cap_ptrace_traceme - Determine whether another process may trace the current |
159 | * @parent: The task proposed to be the tracer | 151 | * @parent: The task proposed to be the tracer |
160 | * | 152 | * |
161 | * If parent is in the same or an ancestor user_ns and has all current's | 153 | * If parent is in the same or an ancestor user_ns and has all current's |
162 | * capabilities, then ptrace access is allowed. | 154 | * capabilities, then ptrace access is allowed. |
163 | * If parent has the ptrace capability to current's user_ns, then ptrace | 155 | * If parent has the ptrace capability to current's user_ns, then ptrace |
164 | * access is allowed. | 156 | * access is allowed. |
165 | * Else denied. | 157 | * Else denied. |
166 | * | 158 | * |
167 | * Determine whether the nominated task is permitted to trace the current | 159 | * Determine whether the nominated task is permitted to trace the current |
168 | * process, returning 0 if permission is granted, -ve if denied. | 160 | * process, returning 0 if permission is granted, -ve if denied. |
169 | */ | 161 | */ |
170 | int cap_ptrace_traceme(struct task_struct *parent) | 162 | int cap_ptrace_traceme(struct task_struct *parent) |
171 | { | 163 | { |
172 | int ret = 0; | 164 | int ret = 0; |
173 | const struct cred *cred, *child_cred; | 165 | const struct cred *cred, *child_cred; |
174 | 166 | ||
175 | rcu_read_lock(); | 167 | rcu_read_lock(); |
176 | cred = __task_cred(parent); | 168 | cred = __task_cred(parent); |
177 | child_cred = current_cred(); | 169 | child_cred = current_cred(); |
178 | if (cred->user->user_ns == child_cred->user->user_ns && | 170 | if (cred->user->user_ns == child_cred->user->user_ns && |
179 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 171 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
180 | goto out; | 172 | goto out; |
181 | if (has_ns_capability(parent, child_cred->user->user_ns, CAP_SYS_PTRACE)) | 173 | if (has_ns_capability(parent, child_cred->user->user_ns, CAP_SYS_PTRACE)) |
182 | goto out; | 174 | goto out; |
183 | ret = -EPERM; | 175 | ret = -EPERM; |
184 | out: | 176 | out: |
185 | rcu_read_unlock(); | 177 | rcu_read_unlock(); |
186 | return ret; | 178 | return ret; |
187 | } | 179 | } |
188 | 180 | ||
189 | /** | 181 | /** |
190 | * cap_capget - Retrieve a task's capability sets | 182 | * cap_capget - Retrieve a task's capability sets |
191 | * @target: The task from which to retrieve the capability sets | 183 | * @target: The task from which to retrieve the capability sets |
192 | * @effective: The place to record the effective set | 184 | * @effective: The place to record the effective set |
193 | * @inheritable: The place to record the inheritable set | 185 | * @inheritable: The place to record the inheritable set |
194 | * @permitted: The place to record the permitted set | 186 | * @permitted: The place to record the permitted set |
195 | * | 187 | * |
196 | * This function retrieves the capabilities of the nominated task and returns | 188 | * This function retrieves the capabilities of the nominated task and returns |
197 | * them to the caller. | 189 | * them to the caller. |
198 | */ | 190 | */ |
199 | int cap_capget(struct task_struct *target, kernel_cap_t *effective, | 191 | int cap_capget(struct task_struct *target, kernel_cap_t *effective, |
200 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 192 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
201 | { | 193 | { |
202 | const struct cred *cred; | 194 | const struct cred *cred; |
203 | 195 | ||
204 | /* Derived from kernel/capability.c:sys_capget. */ | 196 | /* Derived from kernel/capability.c:sys_capget. */ |
205 | rcu_read_lock(); | 197 | rcu_read_lock(); |
206 | cred = __task_cred(target); | 198 | cred = __task_cred(target); |
207 | *effective = cred->cap_effective; | 199 | *effective = cred->cap_effective; |
208 | *inheritable = cred->cap_inheritable; | 200 | *inheritable = cred->cap_inheritable; |
209 | *permitted = cred->cap_permitted; | 201 | *permitted = cred->cap_permitted; |
210 | rcu_read_unlock(); | 202 | rcu_read_unlock(); |
211 | return 0; | 203 | return 0; |
212 | } | 204 | } |
213 | 205 | ||
214 | /* | 206 | /* |
215 | * Determine whether the inheritable capabilities are limited to the old | 207 | * Determine whether the inheritable capabilities are limited to the old |
216 | * permitted set. Returns 1 if they are limited, 0 if they are not. | 208 | * permitted set. Returns 1 if they are limited, 0 if they are not. |
217 | */ | 209 | */ |
218 | static inline int cap_inh_is_capped(void) | 210 | static inline int cap_inh_is_capped(void) |
219 | { | 211 | { |
220 | 212 | ||
221 | /* they are so limited unless the current task has the CAP_SETPCAP | 213 | /* they are so limited unless the current task has the CAP_SETPCAP |
222 | * capability | 214 | * capability |
223 | */ | 215 | */ |
224 | if (cap_capable(current_cred(), current_cred()->user->user_ns, | 216 | if (cap_capable(current_cred(), current_cred()->user->user_ns, |
225 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) | 217 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) |
226 | return 0; | 218 | return 0; |
227 | return 1; | 219 | return 1; |
228 | } | 220 | } |
229 | 221 | ||
230 | /** | 222 | /** |
231 | * cap_capset - Validate and apply proposed changes to current's capabilities | 223 | * cap_capset - Validate and apply proposed changes to current's capabilities |
232 | * @new: The proposed new credentials; alterations should be made here | 224 | * @new: The proposed new credentials; alterations should be made here |
233 | * @old: The current task's current credentials | 225 | * @old: The current task's current credentials |
234 | * @effective: A pointer to the proposed new effective capabilities set | 226 | * @effective: A pointer to the proposed new effective capabilities set |
235 | * @inheritable: A pointer to the proposed new inheritable capabilities set | 227 | * @inheritable: A pointer to the proposed new inheritable capabilities set |
236 | * @permitted: A pointer to the proposed new permitted capabilities set | 228 | * @permitted: A pointer to the proposed new permitted capabilities set |
237 | * | 229 | * |
238 | * This function validates and applies a proposed mass change to the current | 230 | * This function validates and applies a proposed mass change to the current |
239 | * process's capability sets. The changes are made to the proposed new | 231 | * process's capability sets. The changes are made to the proposed new |
240 | * credentials, and assuming no error, will be committed by the caller of LSM. | 232 | * credentials, and assuming no error, will be committed by the caller of LSM. |
241 | */ | 233 | */ |
242 | int cap_capset(struct cred *new, | 234 | int cap_capset(struct cred *new, |
243 | const struct cred *old, | 235 | const struct cred *old, |
244 | const kernel_cap_t *effective, | 236 | const kernel_cap_t *effective, |
245 | const kernel_cap_t *inheritable, | 237 | const kernel_cap_t *inheritable, |
246 | const kernel_cap_t *permitted) | 238 | const kernel_cap_t *permitted) |
247 | { | 239 | { |
248 | if (cap_inh_is_capped() && | 240 | if (cap_inh_is_capped() && |
249 | !cap_issubset(*inheritable, | 241 | !cap_issubset(*inheritable, |
250 | cap_combine(old->cap_inheritable, | 242 | cap_combine(old->cap_inheritable, |
251 | old->cap_permitted))) | 243 | old->cap_permitted))) |
252 | /* incapable of using this inheritable set */ | 244 | /* incapable of using this inheritable set */ |
253 | return -EPERM; | 245 | return -EPERM; |
254 | 246 | ||
255 | if (!cap_issubset(*inheritable, | 247 | if (!cap_issubset(*inheritable, |
256 | cap_combine(old->cap_inheritable, | 248 | cap_combine(old->cap_inheritable, |
257 | old->cap_bset))) | 249 | old->cap_bset))) |
258 | /* no new pI capabilities outside bounding set */ | 250 | /* no new pI capabilities outside bounding set */ |
259 | return -EPERM; | 251 | return -EPERM; |
260 | 252 | ||
261 | /* verify restrictions on target's new Permitted set */ | 253 | /* verify restrictions on target's new Permitted set */ |
262 | if (!cap_issubset(*permitted, old->cap_permitted)) | 254 | if (!cap_issubset(*permitted, old->cap_permitted)) |
263 | return -EPERM; | 255 | return -EPERM; |
264 | 256 | ||
265 | /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ | 257 | /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ |
266 | if (!cap_issubset(*effective, *permitted)) | 258 | if (!cap_issubset(*effective, *permitted)) |
267 | return -EPERM; | 259 | return -EPERM; |
268 | 260 | ||
269 | new->cap_effective = *effective; | 261 | new->cap_effective = *effective; |
270 | new->cap_inheritable = *inheritable; | 262 | new->cap_inheritable = *inheritable; |
271 | new->cap_permitted = *permitted; | 263 | new->cap_permitted = *permitted; |
272 | return 0; | 264 | return 0; |
273 | } | 265 | } |
274 | 266 | ||
275 | /* | 267 | /* |
276 | * Clear proposed capability sets for execve(). | 268 | * Clear proposed capability sets for execve(). |
277 | */ | 269 | */ |
278 | static inline void bprm_clear_caps(struct linux_binprm *bprm) | 270 | static inline void bprm_clear_caps(struct linux_binprm *bprm) |
279 | { | 271 | { |
280 | cap_clear(bprm->cred->cap_permitted); | 272 | cap_clear(bprm->cred->cap_permitted); |
281 | bprm->cap_effective = false; | 273 | bprm->cap_effective = false; |
282 | } | 274 | } |
283 | 275 | ||
284 | /** | 276 | /** |
285 | * cap_inode_need_killpriv - Determine if inode change affects privileges | 277 | * cap_inode_need_killpriv - Determine if inode change affects privileges |
286 | * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV | 278 | * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV |
287 | * | 279 | * |
288 | * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV | 280 | * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV |
289 | * affects the security markings on that inode, and if it is, should | 281 | * affects the security markings on that inode, and if it is, should |
290 | * inode_killpriv() be invoked or the change rejected? | 282 | * inode_killpriv() be invoked or the change rejected? |
291 | * | 283 | * |
292 | * Returns 0 if granted; +ve if granted, but inode_killpriv() is required; and | 284 | * Returns 0 if granted; +ve if granted, but inode_killpriv() is required; and |
293 | * -ve to deny the change. | 285 | * -ve to deny the change. |
294 | */ | 286 | */ |
295 | int cap_inode_need_killpriv(struct dentry *dentry) | 287 | int cap_inode_need_killpriv(struct dentry *dentry) |
296 | { | 288 | { |
297 | struct inode *inode = dentry->d_inode; | 289 | struct inode *inode = dentry->d_inode; |
298 | int error; | 290 | int error; |
299 | 291 | ||
300 | if (!inode->i_op->getxattr) | 292 | if (!inode->i_op->getxattr) |
301 | return 0; | 293 | return 0; |
302 | 294 | ||
303 | error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0); | 295 | error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0); |
304 | if (error <= 0) | 296 | if (error <= 0) |
305 | return 0; | 297 | return 0; |
306 | return 1; | 298 | return 1; |
307 | } | 299 | } |
308 | 300 | ||
309 | /** | 301 | /** |
310 | * cap_inode_killpriv - Erase the security markings on an inode | 302 | * cap_inode_killpriv - Erase the security markings on an inode |
311 | * @dentry: The inode/dentry to alter | 303 | * @dentry: The inode/dentry to alter |
312 | * | 304 | * |
313 | * Erase the privilege-enhancing security markings on an inode. | 305 | * Erase the privilege-enhancing security markings on an inode. |
314 | * | 306 | * |
315 | * Returns 0 if successful, -ve on error. | 307 | * Returns 0 if successful, -ve on error. |
316 | */ | 308 | */ |
317 | int cap_inode_killpriv(struct dentry *dentry) | 309 | int cap_inode_killpriv(struct dentry *dentry) |
318 | { | 310 | { |
319 | struct inode *inode = dentry->d_inode; | 311 | struct inode *inode = dentry->d_inode; |
320 | 312 | ||
321 | if (!inode->i_op->removexattr) | 313 | if (!inode->i_op->removexattr) |
322 | return 0; | 314 | return 0; |
323 | 315 | ||
324 | return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); | 316 | return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); |
325 | } | 317 | } |
326 | 318 | ||
327 | /* | 319 | /* |
328 | * Calculate the new process capability sets from the capability sets attached | 320 | * Calculate the new process capability sets from the capability sets attached |
329 | * to a file. | 321 | * to a file. |
330 | */ | 322 | */ |
331 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | 323 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, |
332 | struct linux_binprm *bprm, | 324 | struct linux_binprm *bprm, |
333 | bool *effective) | 325 | bool *effective) |
334 | { | 326 | { |
335 | struct cred *new = bprm->cred; | 327 | struct cred *new = bprm->cred; |
336 | unsigned i; | 328 | unsigned i; |
337 | int ret = 0; | 329 | int ret = 0; |
338 | 330 | ||
339 | if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) | 331 | if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) |
340 | *effective = true; | 332 | *effective = true; |
341 | 333 | ||
342 | CAP_FOR_EACH_U32(i) { | 334 | CAP_FOR_EACH_U32(i) { |
343 | __u32 permitted = caps->permitted.cap[i]; | 335 | __u32 permitted = caps->permitted.cap[i]; |
344 | __u32 inheritable = caps->inheritable.cap[i]; | 336 | __u32 inheritable = caps->inheritable.cap[i]; |
345 | 337 | ||
346 | /* | 338 | /* |
347 | * pP' = (X & fP) | (pI & fI) | 339 | * pP' = (X & fP) | (pI & fI) |
348 | */ | 340 | */ |
349 | new->cap_permitted.cap[i] = | 341 | new->cap_permitted.cap[i] = |
350 | (new->cap_bset.cap[i] & permitted) | | 342 | (new->cap_bset.cap[i] & permitted) | |
351 | (new->cap_inheritable.cap[i] & inheritable); | 343 | (new->cap_inheritable.cap[i] & inheritable); |
352 | 344 | ||
353 | if (permitted & ~new->cap_permitted.cap[i]) | 345 | if (permitted & ~new->cap_permitted.cap[i]) |
354 | /* insufficient to execute correctly */ | 346 | /* insufficient to execute correctly */ |
355 | ret = -EPERM; | 347 | ret = -EPERM; |
356 | } | 348 | } |
357 | 349 | ||
358 | /* | 350 | /* |
359 | * For legacy apps, with no internal support for recognizing they | 351 | * For legacy apps, with no internal support for recognizing they |
360 | * do not have enough capabilities, we return an error if they are | 352 | * do not have enough capabilities, we return an error if they are |
361 | * missing some "forced" (aka file-permitted) capabilities. | 353 | * missing some "forced" (aka file-permitted) capabilities. |
362 | */ | 354 | */ |
363 | return *effective ? ret : 0; | 355 | return *effective ? ret : 0; |
364 | } | 356 | } |
365 | 357 | ||
366 | /* | 358 | /* |
367 | * Extract the on-exec-apply capability sets for an executable file. | 359 | * Extract the on-exec-apply capability sets for an executable file. |
368 | */ | 360 | */ |
369 | int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) | 361 | int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) |
370 | { | 362 | { |
371 | struct inode *inode = dentry->d_inode; | 363 | struct inode *inode = dentry->d_inode; |
372 | __u32 magic_etc; | 364 | __u32 magic_etc; |
373 | unsigned tocopy, i; | 365 | unsigned tocopy, i; |
374 | int size; | 366 | int size; |
375 | struct vfs_cap_data caps; | 367 | struct vfs_cap_data caps; |
376 | 368 | ||
377 | memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); | 369 | memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); |
378 | 370 | ||
379 | if (!inode || !inode->i_op->getxattr) | 371 | if (!inode || !inode->i_op->getxattr) |
380 | return -ENODATA; | 372 | return -ENODATA; |
381 | 373 | ||
382 | size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, | 374 | size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, |
383 | XATTR_CAPS_SZ); | 375 | XATTR_CAPS_SZ); |
384 | if (size == -ENODATA || size == -EOPNOTSUPP) | 376 | if (size == -ENODATA || size == -EOPNOTSUPP) |
385 | /* no data, that's ok */ | 377 | /* no data, that's ok */ |
386 | return -ENODATA; | 378 | return -ENODATA; |
387 | if (size < 0) | 379 | if (size < 0) |
388 | return size; | 380 | return size; |
389 | 381 | ||
390 | if (size < sizeof(magic_etc)) | 382 | if (size < sizeof(magic_etc)) |
391 | return -EINVAL; | 383 | return -EINVAL; |
392 | 384 | ||
393 | cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); | 385 | cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); |
394 | 386 | ||
395 | switch (magic_etc & VFS_CAP_REVISION_MASK) { | 387 | switch (magic_etc & VFS_CAP_REVISION_MASK) { |
396 | case VFS_CAP_REVISION_1: | 388 | case VFS_CAP_REVISION_1: |
397 | if (size != XATTR_CAPS_SZ_1) | 389 | if (size != XATTR_CAPS_SZ_1) |
398 | return -EINVAL; | 390 | return -EINVAL; |
399 | tocopy = VFS_CAP_U32_1; | 391 | tocopy = VFS_CAP_U32_1; |
400 | break; | 392 | break; |
401 | case VFS_CAP_REVISION_2: | 393 | case VFS_CAP_REVISION_2: |
402 | if (size != XATTR_CAPS_SZ_2) | 394 | if (size != XATTR_CAPS_SZ_2) |
403 | return -EINVAL; | 395 | return -EINVAL; |
404 | tocopy = VFS_CAP_U32_2; | 396 | tocopy = VFS_CAP_U32_2; |
405 | break; | 397 | break; |
406 | default: | 398 | default: |
407 | return -EINVAL; | 399 | return -EINVAL; |
408 | } | 400 | } |
409 | 401 | ||
410 | CAP_FOR_EACH_U32(i) { | 402 | CAP_FOR_EACH_U32(i) { |
411 | if (i >= tocopy) | 403 | if (i >= tocopy) |
412 | break; | 404 | break; |
413 | cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); | 405 | cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); |
414 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); | 406 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); |
415 | } | 407 | } |
416 | 408 | ||
417 | return 0; | 409 | return 0; |
418 | } | 410 | } |
419 | 411 | ||
420 | /* | 412 | /* |
421 | * Attempt to get the on-exec apply capability sets for an executable file from | 413 | * Attempt to get the on-exec apply capability sets for an executable file from |
422 | * its xattrs and, if present, apply them to the proposed credentials being | 414 | * its xattrs and, if present, apply them to the proposed credentials being |
423 | * constructed by execve(). | 415 | * constructed by execve(). |
424 | */ | 416 | */ |
425 | static int get_file_caps(struct linux_binprm *bprm, bool *effective) | 417 | static int get_file_caps(struct linux_binprm *bprm, bool *effective) |
426 | { | 418 | { |
427 | struct dentry *dentry; | 419 | struct dentry *dentry; |
428 | int rc = 0; | 420 | int rc = 0; |
429 | struct cpu_vfs_cap_data vcaps; | 421 | struct cpu_vfs_cap_data vcaps; |
430 | 422 | ||
431 | bprm_clear_caps(bprm); | 423 | bprm_clear_caps(bprm); |
432 | 424 | ||
433 | if (!file_caps_enabled) | 425 | if (!file_caps_enabled) |
434 | return 0; | 426 | return 0; |
435 | 427 | ||
436 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) | 428 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) |
437 | return 0; | 429 | return 0; |
438 | 430 | ||
439 | dentry = dget(bprm->file->f_dentry); | 431 | dentry = dget(bprm->file->f_dentry); |
440 | 432 | ||
441 | rc = get_vfs_caps_from_disk(dentry, &vcaps); | 433 | rc = get_vfs_caps_from_disk(dentry, &vcaps); |
442 | if (rc < 0) { | 434 | if (rc < 0) { |
443 | if (rc == -EINVAL) | 435 | if (rc == -EINVAL) |
444 | printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n", | 436 | printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n", |
445 | __func__, rc, bprm->filename); | 437 | __func__, rc, bprm->filename); |
446 | else if (rc == -ENODATA) | 438 | else if (rc == -ENODATA) |
447 | rc = 0; | 439 | rc = 0; |
448 | goto out; | 440 | goto out; |
449 | } | 441 | } |
450 | 442 | ||
451 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective); | 443 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective); |
452 | if (rc == -EINVAL) | 444 | if (rc == -EINVAL) |
453 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", | 445 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", |
454 | __func__, rc, bprm->filename); | 446 | __func__, rc, bprm->filename); |
455 | 447 | ||
456 | out: | 448 | out: |
457 | dput(dentry); | 449 | dput(dentry); |
458 | if (rc) | 450 | if (rc) |
459 | bprm_clear_caps(bprm); | 451 | bprm_clear_caps(bprm); |
460 | 452 | ||
461 | return rc; | 453 | return rc; |
462 | } | 454 | } |
463 | 455 | ||
464 | /** | 456 | /** |
465 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). | 457 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). |
466 | * @bprm: The execution parameters, including the proposed creds | 458 | * @bprm: The execution parameters, including the proposed creds |
467 | * | 459 | * |
468 | * Set up the proposed credentials for a new execution context being | 460 | * Set up the proposed credentials for a new execution context being |
469 | * constructed by execve(). The proposed creds in @bprm->cred is altered, | 461 | * constructed by execve(). The proposed creds in @bprm->cred is altered, |
470 | * which won't take effect immediately. Returns 0 if successful, -ve on error. | 462 | * which won't take effect immediately. Returns 0 if successful, -ve on error. |
471 | */ | 463 | */ |
472 | int cap_bprm_set_creds(struct linux_binprm *bprm) | 464 | int cap_bprm_set_creds(struct linux_binprm *bprm) |
473 | { | 465 | { |
474 | const struct cred *old = current_cred(); | 466 | const struct cred *old = current_cred(); |
475 | struct cred *new = bprm->cred; | 467 | struct cred *new = bprm->cred; |
476 | bool effective; | 468 | bool effective; |
477 | int ret; | 469 | int ret; |
478 | 470 | ||
479 | effective = false; | 471 | effective = false; |
480 | ret = get_file_caps(bprm, &effective); | 472 | ret = get_file_caps(bprm, &effective); |
481 | if (ret < 0) | 473 | if (ret < 0) |
482 | return ret; | 474 | return ret; |
483 | 475 | ||
484 | if (!issecure(SECURE_NOROOT)) { | 476 | if (!issecure(SECURE_NOROOT)) { |
485 | /* | 477 | /* |
486 | * If the legacy file capability is set, then don't set privs | 478 | * If the legacy file capability is set, then don't set privs |
487 | * for a setuid root binary run by a non-root user. Do set it | 479 | * for a setuid root binary run by a non-root user. Do set it |
488 | * for a root user just to cause least surprise to an admin. | 480 | * for a root user just to cause least surprise to an admin. |
489 | */ | 481 | */ |
490 | if (effective && new->uid != 0 && new->euid == 0) { | 482 | if (effective && new->uid != 0 && new->euid == 0) { |
491 | warn_setuid_and_fcaps_mixed(bprm->filename); | 483 | warn_setuid_and_fcaps_mixed(bprm->filename); |
492 | goto skip; | 484 | goto skip; |
493 | } | 485 | } |
494 | /* | 486 | /* |
495 | * To support inheritance of root-permissions and suid-root | 487 | * To support inheritance of root-permissions and suid-root |
496 | * executables under compatibility mode, we override the | 488 | * executables under compatibility mode, we override the |
497 | * capability sets for the file. | 489 | * capability sets for the file. |
498 | * | 490 | * |
499 | * If only the real uid is 0, we do not set the effective bit. | 491 | * If only the real uid is 0, we do not set the effective bit. |
500 | */ | 492 | */ |
501 | if (new->euid == 0 || new->uid == 0) { | 493 | if (new->euid == 0 || new->uid == 0) { |
502 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | 494 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ |
503 | new->cap_permitted = cap_combine(old->cap_bset, | 495 | new->cap_permitted = cap_combine(old->cap_bset, |
504 | old->cap_inheritable); | 496 | old->cap_inheritable); |
505 | } | 497 | } |
506 | if (new->euid == 0) | 498 | if (new->euid == 0) |
507 | effective = true; | 499 | effective = true; |
508 | } | 500 | } |
509 | skip: | 501 | skip: |
510 | 502 | ||
511 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised | 503 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised |
512 | * credentials unless they have the appropriate permit | 504 | * credentials unless they have the appropriate permit |
513 | */ | 505 | */ |
514 | if ((new->euid != old->uid || | 506 | if ((new->euid != old->uid || |
515 | new->egid != old->gid || | 507 | new->egid != old->gid || |
516 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && | 508 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && |
517 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | 509 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { |
518 | /* downgrade; they get no more than they had, and maybe less */ | 510 | /* downgrade; they get no more than they had, and maybe less */ |
519 | if (!capable(CAP_SETUID)) { | 511 | if (!capable(CAP_SETUID)) { |
520 | new->euid = new->uid; | 512 | new->euid = new->uid; |
521 | new->egid = new->gid; | 513 | new->egid = new->gid; |
522 | } | 514 | } |
523 | new->cap_permitted = cap_intersect(new->cap_permitted, | 515 | new->cap_permitted = cap_intersect(new->cap_permitted, |
524 | old->cap_permitted); | 516 | old->cap_permitted); |
525 | } | 517 | } |
526 | 518 | ||
527 | new->suid = new->fsuid = new->euid; | 519 | new->suid = new->fsuid = new->euid; |
528 | new->sgid = new->fsgid = new->egid; | 520 | new->sgid = new->fsgid = new->egid; |
529 | 521 | ||
530 | if (effective) | 522 | if (effective) |
531 | new->cap_effective = new->cap_permitted; | 523 | new->cap_effective = new->cap_permitted; |
532 | else | 524 | else |
533 | cap_clear(new->cap_effective); | 525 | cap_clear(new->cap_effective); |
534 | bprm->cap_effective = effective; | 526 | bprm->cap_effective = effective; |
535 | 527 | ||
536 | /* | 528 | /* |
537 | * Audit candidate if current->cap_effective is set | 529 | * Audit candidate if current->cap_effective is set |
538 | * | 530 | * |
539 | * We do not bother to audit if 3 things are true: | 531 | * We do not bother to audit if 3 things are true: |
540 | * 1) cap_effective has all caps | 532 | * 1) cap_effective has all caps |
541 | * 2) we are root | 533 | * 2) we are root |
542 | * 3) root is supposed to have all caps (SECURE_NOROOT) | 534 | * 3) root is supposed to have all caps (SECURE_NOROOT) |
543 | * Since this is just a normal root execing a process. | 535 | * Since this is just a normal root execing a process. |
544 | * | 536 | * |
545 | * Number 1 above might fail if you don't have a full bset, but I think | 537 | * Number 1 above might fail if you don't have a full bset, but I think |
546 | * that is interesting information to audit. | 538 | * that is interesting information to audit. |
547 | */ | 539 | */ |
548 | if (!cap_isclear(new->cap_effective)) { | 540 | if (!cap_isclear(new->cap_effective)) { |
549 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || | 541 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || |
550 | new->euid != 0 || new->uid != 0 || | 542 | new->euid != 0 || new->uid != 0 || |
551 | issecure(SECURE_NOROOT)) { | 543 | issecure(SECURE_NOROOT)) { |
552 | ret = audit_log_bprm_fcaps(bprm, new, old); | 544 | ret = audit_log_bprm_fcaps(bprm, new, old); |
553 | if (ret < 0) | 545 | if (ret < 0) |
554 | return ret; | 546 | return ret; |
555 | } | 547 | } |
556 | } | 548 | } |
557 | 549 | ||
558 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 550 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
559 | return 0; | 551 | return 0; |
560 | } | 552 | } |
561 | 553 | ||
562 | /** | 554 | /** |
563 | * cap_bprm_secureexec - Determine whether a secure execution is required | 555 | * cap_bprm_secureexec - Determine whether a secure execution is required |
564 | * @bprm: The execution parameters | 556 | * @bprm: The execution parameters |
565 | * | 557 | * |
566 | * Determine whether a secure execution is required, return 1 if it is, and 0 | 558 | * Determine whether a secure execution is required, return 1 if it is, and 0 |
567 | * if it is not. | 559 | * if it is not. |
568 | * | 560 | * |
569 | * The credentials have been committed by this point, and so are no longer | 561 | * The credentials have been committed by this point, and so are no longer |
570 | * available through @bprm->cred. | 562 | * available through @bprm->cred. |
571 | */ | 563 | */ |
572 | int cap_bprm_secureexec(struct linux_binprm *bprm) | 564 | int cap_bprm_secureexec(struct linux_binprm *bprm) |
573 | { | 565 | { |
574 | const struct cred *cred = current_cred(); | 566 | const struct cred *cred = current_cred(); |
575 | 567 | ||
576 | if (cred->uid != 0) { | 568 | if (cred->uid != 0) { |
577 | if (bprm->cap_effective) | 569 | if (bprm->cap_effective) |
578 | return 1; | 570 | return 1; |
579 | if (!cap_isclear(cred->cap_permitted)) | 571 | if (!cap_isclear(cred->cap_permitted)) |
580 | return 1; | 572 | return 1; |
581 | } | 573 | } |
582 | 574 | ||
583 | return (cred->euid != cred->uid || | 575 | return (cred->euid != cred->uid || |
584 | cred->egid != cred->gid); | 576 | cred->egid != cred->gid); |
585 | } | 577 | } |
586 | 578 | ||
587 | /** | 579 | /** |
588 | * cap_inode_setxattr - Determine whether an xattr may be altered | 580 | * cap_inode_setxattr - Determine whether an xattr may be altered |
589 | * @dentry: The inode/dentry being altered | 581 | * @dentry: The inode/dentry being altered |
590 | * @name: The name of the xattr to be changed | 582 | * @name: The name of the xattr to be changed |
591 | * @value: The value that the xattr will be changed to | 583 | * @value: The value that the xattr will be changed to |
592 | * @size: The size of value | 584 | * @size: The size of value |
593 | * @flags: The replacement flag | 585 | * @flags: The replacement flag |
594 | * | 586 | * |
595 | * Determine whether an xattr may be altered or set on an inode, returning 0 if | 587 | * Determine whether an xattr may be altered or set on an inode, returning 0 if |
596 | * permission is granted, -ve if denied. | 588 | * permission is granted, -ve if denied. |
597 | * | 589 | * |
598 | * This is used to make sure security xattrs don't get updated or set by those | 590 | * This is used to make sure security xattrs don't get updated or set by those |
599 | * who aren't privileged to do so. | 591 | * who aren't privileged to do so. |
600 | */ | 592 | */ |
601 | int cap_inode_setxattr(struct dentry *dentry, const char *name, | 593 | int cap_inode_setxattr(struct dentry *dentry, const char *name, |
602 | const void *value, size_t size, int flags) | 594 | const void *value, size_t size, int flags) |
603 | { | 595 | { |
604 | if (!strcmp(name, XATTR_NAME_CAPS)) { | 596 | if (!strcmp(name, XATTR_NAME_CAPS)) { |
605 | if (!capable(CAP_SETFCAP)) | 597 | if (!capable(CAP_SETFCAP)) |
606 | return -EPERM; | 598 | return -EPERM; |
607 | return 0; | 599 | return 0; |
608 | } | 600 | } |
609 | 601 | ||
610 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 602 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
611 | sizeof(XATTR_SECURITY_PREFIX) - 1) && | 603 | sizeof(XATTR_SECURITY_PREFIX) - 1) && |
612 | !capable(CAP_SYS_ADMIN)) | 604 | !capable(CAP_SYS_ADMIN)) |
613 | return -EPERM; | 605 | return -EPERM; |
614 | return 0; | 606 | return 0; |
615 | } | 607 | } |
616 | 608 | ||
617 | /** | 609 | /** |
618 | * cap_inode_removexattr - Determine whether an xattr may be removed | 610 | * cap_inode_removexattr - Determine whether an xattr may be removed |
619 | * @dentry: The inode/dentry being altered | 611 | * @dentry: The inode/dentry being altered |
620 | * @name: The name of the xattr to be changed | 612 | * @name: The name of the xattr to be changed |
621 | * | 613 | * |
622 | * Determine whether an xattr may be removed from an inode, returning 0 if | 614 | * Determine whether an xattr may be removed from an inode, returning 0 if |
623 | * permission is granted, -ve if denied. | 615 | * permission is granted, -ve if denied. |
624 | * | 616 | * |
625 | * This is used to make sure security xattrs don't get removed by those who | 617 | * This is used to make sure security xattrs don't get removed by those who |
626 | * aren't privileged to remove them. | 618 | * aren't privileged to remove them. |
627 | */ | 619 | */ |
628 | int cap_inode_removexattr(struct dentry *dentry, const char *name) | 620 | int cap_inode_removexattr(struct dentry *dentry, const char *name) |
629 | { | 621 | { |
630 | if (!strcmp(name, XATTR_NAME_CAPS)) { | 622 | if (!strcmp(name, XATTR_NAME_CAPS)) { |
631 | if (!capable(CAP_SETFCAP)) | 623 | if (!capable(CAP_SETFCAP)) |
632 | return -EPERM; | 624 | return -EPERM; |
633 | return 0; | 625 | return 0; |
634 | } | 626 | } |
635 | 627 | ||
636 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 628 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
637 | sizeof(XATTR_SECURITY_PREFIX) - 1) && | 629 | sizeof(XATTR_SECURITY_PREFIX) - 1) && |
638 | !capable(CAP_SYS_ADMIN)) | 630 | !capable(CAP_SYS_ADMIN)) |
639 | return -EPERM; | 631 | return -EPERM; |
640 | return 0; | 632 | return 0; |
641 | } | 633 | } |
642 | 634 | ||
643 | /* | 635 | /* |
644 | * cap_emulate_setxuid() fixes the effective / permitted capabilities of | 636 | * cap_emulate_setxuid() fixes the effective / permitted capabilities of |
645 | * a process after a call to setuid, setreuid, or setresuid. | 637 | * a process after a call to setuid, setreuid, or setresuid. |
646 | * | 638 | * |
647 | * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of | 639 | * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of |
648 | * {r,e,s}uid != 0, the permitted and effective capabilities are | 640 | * {r,e,s}uid != 0, the permitted and effective capabilities are |
649 | * cleared. | 641 | * cleared. |
650 | * | 642 | * |
651 | * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective | 643 | * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective |
652 | * capabilities of the process are cleared. | 644 | * capabilities of the process are cleared. |
653 | * | 645 | * |
654 | * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective | 646 | * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective |
655 | * capabilities are set to the permitted capabilities. | 647 | * capabilities are set to the permitted capabilities. |
656 | * | 648 | * |
657 | * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should | 649 | * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should |
658 | * never happen. | 650 | * never happen. |
659 | * | 651 | * |
660 | * -astor | 652 | * -astor |
661 | * | 653 | * |
662 | * cevans - New behaviour, Oct '99 | 654 | * cevans - New behaviour, Oct '99 |
663 | * A process may, via prctl(), elect to keep its capabilities when it | 655 | * A process may, via prctl(), elect to keep its capabilities when it |
664 | * calls setuid() and switches away from uid==0. Both permitted and | 656 | * calls setuid() and switches away from uid==0. Both permitted and |
665 | * effective sets will be retained. | 657 | * effective sets will be retained. |
666 | * Without this change, it was impossible for a daemon to drop only some | 658 | * Without this change, it was impossible for a daemon to drop only some |
667 | * of its privilege. The call to setuid(!=0) would drop all privileges! | 659 | * of its privilege. The call to setuid(!=0) would drop all privileges! |
668 | * Keeping uid 0 is not an option because uid 0 owns too many vital | 660 | * Keeping uid 0 is not an option because uid 0 owns too many vital |
669 | * files.. | 661 | * files.. |
670 | * Thanks to Olaf Kirch and Peter Benie for spotting this. | 662 | * Thanks to Olaf Kirch and Peter Benie for spotting this. |
671 | */ | 663 | */ |
672 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) | 664 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) |
673 | { | 665 | { |
674 | if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && | 666 | if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && |
675 | (new->uid != 0 && new->euid != 0 && new->suid != 0) && | 667 | (new->uid != 0 && new->euid != 0 && new->suid != 0) && |
676 | !issecure(SECURE_KEEP_CAPS)) { | 668 | !issecure(SECURE_KEEP_CAPS)) { |
677 | cap_clear(new->cap_permitted); | 669 | cap_clear(new->cap_permitted); |
678 | cap_clear(new->cap_effective); | 670 | cap_clear(new->cap_effective); |
679 | } | 671 | } |
680 | if (old->euid == 0 && new->euid != 0) | 672 | if (old->euid == 0 && new->euid != 0) |
681 | cap_clear(new->cap_effective); | 673 | cap_clear(new->cap_effective); |
682 | if (old->euid != 0 && new->euid == 0) | 674 | if (old->euid != 0 && new->euid == 0) |
683 | new->cap_effective = new->cap_permitted; | 675 | new->cap_effective = new->cap_permitted; |
684 | } | 676 | } |
685 | 677 | ||
686 | /** | 678 | /** |
687 | * cap_task_fix_setuid - Fix up the results of setuid() call | 679 | * cap_task_fix_setuid - Fix up the results of setuid() call |
688 | * @new: The proposed credentials | 680 | * @new: The proposed credentials |
689 | * @old: The current task's current credentials | 681 | * @old: The current task's current credentials |
690 | * @flags: Indications of what has changed | 682 | * @flags: Indications of what has changed |
691 | * | 683 | * |
692 | * Fix up the results of setuid() call before the credential changes are | 684 | * Fix up the results of setuid() call before the credential changes are |
693 | * actually applied, returning 0 to grant the changes, -ve to deny them. | 685 | * actually applied, returning 0 to grant the changes, -ve to deny them. |
694 | */ | 686 | */ |
695 | int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) | 687 | int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) |
696 | { | 688 | { |
697 | switch (flags) { | 689 | switch (flags) { |
698 | case LSM_SETID_RE: | 690 | case LSM_SETID_RE: |
699 | case LSM_SETID_ID: | 691 | case LSM_SETID_ID: |
700 | case LSM_SETID_RES: | 692 | case LSM_SETID_RES: |
701 | /* juggle the capabilities to follow [RES]UID changes unless | 693 | /* juggle the capabilities to follow [RES]UID changes unless |
702 | * otherwise suppressed */ | 694 | * otherwise suppressed */ |
703 | if (!issecure(SECURE_NO_SETUID_FIXUP)) | 695 | if (!issecure(SECURE_NO_SETUID_FIXUP)) |
704 | cap_emulate_setxuid(new, old); | 696 | cap_emulate_setxuid(new, old); |
705 | break; | 697 | break; |
706 | 698 | ||
707 | case LSM_SETID_FS: | 699 | case LSM_SETID_FS: |
708 | /* juggle the capabilties to follow FSUID changes, unless | 700 | /* juggle the capabilties to follow FSUID changes, unless |
709 | * otherwise suppressed | 701 | * otherwise suppressed |
710 | * | 702 | * |
711 | * FIXME - is fsuser used for all CAP_FS_MASK capabilities? | 703 | * FIXME - is fsuser used for all CAP_FS_MASK capabilities? |
712 | * if not, we might be a bit too harsh here. | 704 | * if not, we might be a bit too harsh here. |
713 | */ | 705 | */ |
714 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 706 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
715 | if (old->fsuid == 0 && new->fsuid != 0) | 707 | if (old->fsuid == 0 && new->fsuid != 0) |
716 | new->cap_effective = | 708 | new->cap_effective = |
717 | cap_drop_fs_set(new->cap_effective); | 709 | cap_drop_fs_set(new->cap_effective); |
718 | 710 | ||
719 | if (old->fsuid != 0 && new->fsuid == 0) | 711 | if (old->fsuid != 0 && new->fsuid == 0) |
720 | new->cap_effective = | 712 | new->cap_effective = |
721 | cap_raise_fs_set(new->cap_effective, | 713 | cap_raise_fs_set(new->cap_effective, |
722 | new->cap_permitted); | 714 | new->cap_permitted); |
723 | } | 715 | } |
724 | break; | 716 | break; |
725 | 717 | ||
726 | default: | 718 | default: |
727 | return -EINVAL; | 719 | return -EINVAL; |
728 | } | 720 | } |
729 | 721 | ||
730 | return 0; | 722 | return 0; |
731 | } | 723 | } |
732 | 724 | ||
733 | /* | 725 | /* |
734 | * Rationale: code calling task_setscheduler, task_setioprio, and | 726 | * Rationale: code calling task_setscheduler, task_setioprio, and |
735 | * task_setnice, assumes that | 727 | * task_setnice, assumes that |
736 | * . if capable(cap_sys_nice), then those actions should be allowed | 728 | * . if capable(cap_sys_nice), then those actions should be allowed |
737 | * . if not capable(cap_sys_nice), but acting on your own processes, | 729 | * . if not capable(cap_sys_nice), but acting on your own processes, |
738 | * then those actions should be allowed | 730 | * then those actions should be allowed |
739 | * This is insufficient now since you can call code without suid, but | 731 | * This is insufficient now since you can call code without suid, but |
740 | * yet with increased caps. | 732 | * yet with increased caps. |
741 | * So we check for increased caps on the target process. | 733 | * So we check for increased caps on the target process. |
742 | */ | 734 | */ |
743 | static int cap_safe_nice(struct task_struct *p) | 735 | static int cap_safe_nice(struct task_struct *p) |
744 | { | 736 | { |
745 | int is_subset; | 737 | int is_subset; |
746 | 738 | ||
747 | rcu_read_lock(); | 739 | rcu_read_lock(); |
748 | is_subset = cap_issubset(__task_cred(p)->cap_permitted, | 740 | is_subset = cap_issubset(__task_cred(p)->cap_permitted, |
749 | current_cred()->cap_permitted); | 741 | current_cred()->cap_permitted); |
750 | rcu_read_unlock(); | 742 | rcu_read_unlock(); |
751 | 743 | ||
752 | if (!is_subset && !capable(CAP_SYS_NICE)) | 744 | if (!is_subset && !capable(CAP_SYS_NICE)) |
753 | return -EPERM; | 745 | return -EPERM; |
754 | return 0; | 746 | return 0; |
755 | } | 747 | } |
756 | 748 | ||
757 | /** | 749 | /** |
758 | * cap_task_setscheduler - Detemine if scheduler policy change is permitted | 750 | * cap_task_setscheduler - Detemine if scheduler policy change is permitted |
759 | * @p: The task to affect | 751 | * @p: The task to affect |
760 | * | 752 | * |
761 | * Detemine if the requested scheduler policy change is permitted for the | 753 | * Detemine if the requested scheduler policy change is permitted for the |
762 | * specified task, returning 0 if permission is granted, -ve if denied. | 754 | * specified task, returning 0 if permission is granted, -ve if denied. |
763 | */ | 755 | */ |
764 | int cap_task_setscheduler(struct task_struct *p) | 756 | int cap_task_setscheduler(struct task_struct *p) |
765 | { | 757 | { |
766 | return cap_safe_nice(p); | 758 | return cap_safe_nice(p); |
767 | } | 759 | } |
768 | 760 | ||
769 | /** | 761 | /** |
770 | * cap_task_ioprio - Detemine if I/O priority change is permitted | 762 | * cap_task_ioprio - Detemine if I/O priority change is permitted |
771 | * @p: The task to affect | 763 | * @p: The task to affect |
772 | * @ioprio: The I/O priority to set | 764 | * @ioprio: The I/O priority to set |
773 | * | 765 | * |
774 | * Detemine if the requested I/O priority change is permitted for the specified | 766 | * Detemine if the requested I/O priority change is permitted for the specified |
775 | * task, returning 0 if permission is granted, -ve if denied. | 767 | * task, returning 0 if permission is granted, -ve if denied. |
776 | */ | 768 | */ |
777 | int cap_task_setioprio(struct task_struct *p, int ioprio) | 769 | int cap_task_setioprio(struct task_struct *p, int ioprio) |
778 | { | 770 | { |
779 | return cap_safe_nice(p); | 771 | return cap_safe_nice(p); |
780 | } | 772 | } |
781 | 773 | ||
782 | /** | 774 | /** |
783 | * cap_task_ioprio - Detemine if task priority change is permitted | 775 | * cap_task_ioprio - Detemine if task priority change is permitted |
784 | * @p: The task to affect | 776 | * @p: The task to affect |
785 | * @nice: The nice value to set | 777 | * @nice: The nice value to set |
786 | * | 778 | * |
787 | * Detemine if the requested task priority change is permitted for the | 779 | * Detemine if the requested task priority change is permitted for the |
788 | * specified task, returning 0 if permission is granted, -ve if denied. | 780 | * specified task, returning 0 if permission is granted, -ve if denied. |
789 | */ | 781 | */ |
790 | int cap_task_setnice(struct task_struct *p, int nice) | 782 | int cap_task_setnice(struct task_struct *p, int nice) |
791 | { | 783 | { |
792 | return cap_safe_nice(p); | 784 | return cap_safe_nice(p); |
793 | } | 785 | } |
794 | 786 | ||
795 | /* | 787 | /* |
796 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from | 788 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from |
797 | * the current task's bounding set. Returns 0 on success, -ve on error. | 789 | * the current task's bounding set. Returns 0 on success, -ve on error. |
798 | */ | 790 | */ |
799 | static long cap_prctl_drop(struct cred *new, unsigned long cap) | 791 | static long cap_prctl_drop(struct cred *new, unsigned long cap) |
800 | { | 792 | { |
801 | if (!capable(CAP_SETPCAP)) | 793 | if (!capable(CAP_SETPCAP)) |
802 | return -EPERM; | 794 | return -EPERM; |
803 | if (!cap_valid(cap)) | 795 | if (!cap_valid(cap)) |
804 | return -EINVAL; | 796 | return -EINVAL; |
805 | 797 | ||
806 | cap_lower(new->cap_bset, cap); | 798 | cap_lower(new->cap_bset, cap); |
807 | return 0; | 799 | return 0; |
808 | } | 800 | } |
809 | 801 | ||
810 | /** | 802 | /** |
811 | * cap_task_prctl - Implement process control functions for this security module | 803 | * cap_task_prctl - Implement process control functions for this security module |
812 | * @option: The process control function requested | 804 | * @option: The process control function requested |
813 | * @arg2, @arg3, @arg4, @arg5: The argument data for this function | 805 | * @arg2, @arg3, @arg4, @arg5: The argument data for this function |
814 | * | 806 | * |
815 | * Allow process control functions (sys_prctl()) to alter capabilities; may | 807 | * Allow process control functions (sys_prctl()) to alter capabilities; may |
816 | * also deny access to other functions not otherwise implemented here. | 808 | * also deny access to other functions not otherwise implemented here. |
817 | * | 809 | * |
818 | * Returns 0 or +ve on success, -ENOSYS if this function is not implemented | 810 | * Returns 0 or +ve on success, -ENOSYS if this function is not implemented |
819 | * here, other -ve on error. If -ENOSYS is returned, sys_prctl() and other LSM | 811 | * here, other -ve on error. If -ENOSYS is returned, sys_prctl() and other LSM |
820 | * modules will consider performing the function. | 812 | * modules will consider performing the function. |
821 | */ | 813 | */ |
822 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 814 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
823 | unsigned long arg4, unsigned long arg5) | 815 | unsigned long arg4, unsigned long arg5) |
824 | { | 816 | { |
825 | struct cred *new; | 817 | struct cred *new; |
826 | long error = 0; | 818 | long error = 0; |
827 | 819 | ||
828 | new = prepare_creds(); | 820 | new = prepare_creds(); |
829 | if (!new) | 821 | if (!new) |
830 | return -ENOMEM; | 822 | return -ENOMEM; |
831 | 823 | ||
832 | switch (option) { | 824 | switch (option) { |
833 | case PR_CAPBSET_READ: | 825 | case PR_CAPBSET_READ: |
834 | error = -EINVAL; | 826 | error = -EINVAL; |
835 | if (!cap_valid(arg2)) | 827 | if (!cap_valid(arg2)) |
836 | goto error; | 828 | goto error; |
837 | error = !!cap_raised(new->cap_bset, arg2); | 829 | error = !!cap_raised(new->cap_bset, arg2); |
838 | goto no_change; | 830 | goto no_change; |
839 | 831 | ||
840 | case PR_CAPBSET_DROP: | 832 | case PR_CAPBSET_DROP: |
841 | error = cap_prctl_drop(new, arg2); | 833 | error = cap_prctl_drop(new, arg2); |
842 | if (error < 0) | 834 | if (error < 0) |
843 | goto error; | 835 | goto error; |
844 | goto changed; | 836 | goto changed; |
845 | 837 | ||
846 | /* | 838 | /* |
847 | * The next four prctl's remain to assist with transitioning a | 839 | * The next four prctl's remain to assist with transitioning a |
848 | * system from legacy UID=0 based privilege (when filesystem | 840 | * system from legacy UID=0 based privilege (when filesystem |
849 | * capabilities are not in use) to a system using filesystem | 841 | * capabilities are not in use) to a system using filesystem |
850 | * capabilities only - as the POSIX.1e draft intended. | 842 | * capabilities only - as the POSIX.1e draft intended. |
851 | * | 843 | * |
852 | * Note: | 844 | * Note: |
853 | * | 845 | * |
854 | * PR_SET_SECUREBITS = | 846 | * PR_SET_SECUREBITS = |
855 | * issecure_mask(SECURE_KEEP_CAPS_LOCKED) | 847 | * issecure_mask(SECURE_KEEP_CAPS_LOCKED) |
856 | * | issecure_mask(SECURE_NOROOT) | 848 | * | issecure_mask(SECURE_NOROOT) |
857 | * | issecure_mask(SECURE_NOROOT_LOCKED) | 849 | * | issecure_mask(SECURE_NOROOT_LOCKED) |
858 | * | issecure_mask(SECURE_NO_SETUID_FIXUP) | 850 | * | issecure_mask(SECURE_NO_SETUID_FIXUP) |
859 | * | issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED) | 851 | * | issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED) |
860 | * | 852 | * |
861 | * will ensure that the current process and all of its | 853 | * will ensure that the current process and all of its |
862 | * children will be locked into a pure | 854 | * children will be locked into a pure |
863 | * capability-based-privilege environment. | 855 | * capability-based-privilege environment. |
864 | */ | 856 | */ |
865 | case PR_SET_SECUREBITS: | 857 | case PR_SET_SECUREBITS: |
866 | error = -EPERM; | 858 | error = -EPERM; |
867 | if ((((new->securebits & SECURE_ALL_LOCKS) >> 1) | 859 | if ((((new->securebits & SECURE_ALL_LOCKS) >> 1) |
868 | & (new->securebits ^ arg2)) /*[1]*/ | 860 | & (new->securebits ^ arg2)) /*[1]*/ |
869 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | 861 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
870 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 862 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
871 | || (cap_capable(current_cred(), | 863 | || (cap_capable(current_cred(), |
872 | current_cred()->user->user_ns, CAP_SETPCAP, | 864 | current_cred()->user->user_ns, CAP_SETPCAP, |
873 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ | 865 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ |
874 | /* | 866 | /* |
875 | * [1] no changing of bits that are locked | 867 | * [1] no changing of bits that are locked |
876 | * [2] no unlocking of locks | 868 | * [2] no unlocking of locks |
877 | * [3] no setting of unsupported bits | 869 | * [3] no setting of unsupported bits |
878 | * [4] doing anything requires privilege (go read about | 870 | * [4] doing anything requires privilege (go read about |
879 | * the "sendmail capabilities bug") | 871 | * the "sendmail capabilities bug") |
880 | */ | 872 | */ |
881 | ) | 873 | ) |
882 | /* cannot change a locked bit */ | 874 | /* cannot change a locked bit */ |
883 | goto error; | 875 | goto error; |
884 | new->securebits = arg2; | 876 | new->securebits = arg2; |
885 | goto changed; | 877 | goto changed; |
886 | 878 | ||
887 | case PR_GET_SECUREBITS: | 879 | case PR_GET_SECUREBITS: |
888 | error = new->securebits; | 880 | error = new->securebits; |
889 | goto no_change; | 881 | goto no_change; |
890 | 882 | ||
891 | case PR_GET_KEEPCAPS: | 883 | case PR_GET_KEEPCAPS: |
892 | if (issecure(SECURE_KEEP_CAPS)) | 884 | if (issecure(SECURE_KEEP_CAPS)) |
893 | error = 1; | 885 | error = 1; |
894 | goto no_change; | 886 | goto no_change; |
895 | 887 | ||
896 | case PR_SET_KEEPCAPS: | 888 | case PR_SET_KEEPCAPS: |
897 | error = -EINVAL; | 889 | error = -EINVAL; |
898 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ | 890 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ |
899 | goto error; | 891 | goto error; |
900 | error = -EPERM; | 892 | error = -EPERM; |
901 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) | 893 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) |
902 | goto error; | 894 | goto error; |
903 | if (arg2) | 895 | if (arg2) |
904 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); | 896 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); |
905 | else | 897 | else |
906 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 898 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
907 | goto changed; | 899 | goto changed; |
908 | 900 | ||
909 | default: | 901 | default: |
910 | /* No functionality available - continue with default */ | 902 | /* No functionality available - continue with default */ |
911 | error = -ENOSYS; | 903 | error = -ENOSYS; |
912 | goto error; | 904 | goto error; |
913 | } | 905 | } |
914 | 906 | ||
915 | /* Functionality provided */ | 907 | /* Functionality provided */ |
916 | changed: | 908 | changed: |
917 | return commit_creds(new); | 909 | return commit_creds(new); |
918 | 910 | ||
919 | no_change: | 911 | no_change: |
920 | error: | 912 | error: |
921 | abort_creds(new); | 913 | abort_creds(new); |
922 | return error; | 914 | return error; |
923 | } | 915 | } |
924 | 916 | ||
925 | /** | 917 | /** |
926 | * cap_vm_enough_memory - Determine whether a new virtual mapping is permitted | 918 | * cap_vm_enough_memory - Determine whether a new virtual mapping is permitted |
927 | * @mm: The VM space in which the new mapping is to be made | 919 | * @mm: The VM space in which the new mapping is to be made |
928 | * @pages: The size of the mapping | 920 | * @pages: The size of the mapping |
929 | * | 921 | * |
930 | * Determine whether the allocation of a new virtual mapping by the current | 922 | * Determine whether the allocation of a new virtual mapping by the current |
931 | * task is permitted, returning 0 if permission is granted, -ve if not. | 923 | * task is permitted, returning 0 if permission is granted, -ve if not. |
932 | */ | 924 | */ |
933 | int cap_vm_enough_memory(struct mm_struct *mm, long pages) | 925 | int cap_vm_enough_memory(struct mm_struct *mm, long pages) |
934 | { | 926 | { |
935 | int cap_sys_admin = 0; | 927 | int cap_sys_admin = 0; |
936 | 928 | ||
937 | if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, | 929 | if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, |
938 | SECURITY_CAP_NOAUDIT) == 0) | 930 | SECURITY_CAP_NOAUDIT) == 0) |
939 | cap_sys_admin = 1; | 931 | cap_sys_admin = 1; |
940 | return __vm_enough_memory(mm, pages, cap_sys_admin); | 932 | return __vm_enough_memory(mm, pages, cap_sys_admin); |
941 | } | 933 | } |
942 | 934 | ||
943 | /* | 935 | /* |
944 | * cap_file_mmap - check if able to map given addr | 936 | * cap_file_mmap - check if able to map given addr |
945 | * @file: unused | 937 | * @file: unused |
946 | * @reqprot: unused | 938 | * @reqprot: unused |
947 | * @prot: unused | 939 | * @prot: unused |
948 | * @flags: unused | 940 | * @flags: unused |
949 | * @addr: address attempting to be mapped | 941 | * @addr: address attempting to be mapped |
950 | * @addr_only: unused | 942 | * @addr_only: unused |
951 | * | 943 | * |
952 | * If the process is attempting to map memory below dac_mmap_min_addr they need | 944 | * If the process is attempting to map memory below dac_mmap_min_addr they need |
953 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the | 945 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the |
954 | * capability security module. Returns 0 if this mapping should be allowed | 946 | * capability security module. Returns 0 if this mapping should be allowed |
955 | * -EPERM if not. | 947 | * -EPERM if not. |
956 | */ | 948 | */ |
957 | int cap_file_mmap(struct file *file, unsigned long reqprot, | 949 | int cap_file_mmap(struct file *file, unsigned long reqprot, |
958 | unsigned long prot, unsigned long flags, | 950 | unsigned long prot, unsigned long flags, |
959 | unsigned long addr, unsigned long addr_only) | 951 | unsigned long addr, unsigned long addr_only) |
960 | { | 952 | { |
961 | int ret = 0; | 953 | int ret = 0; |
962 | 954 | ||
963 | if (addr < dac_mmap_min_addr) { | 955 | if (addr < dac_mmap_min_addr) { |
964 | ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, | 956 | ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, |
965 | SECURITY_CAP_AUDIT); | 957 | SECURITY_CAP_AUDIT); |
966 | /* set PF_SUPERPRIV if it turns out we allow the low mmap */ | 958 | /* set PF_SUPERPRIV if it turns out we allow the low mmap */ |
967 | if (ret == 0) | 959 | if (ret == 0) |
968 | current->flags |= PF_SUPERPRIV; | 960 | current->flags |= PF_SUPERPRIV; |
969 | } | 961 | } |
970 | return ret; | 962 | return ret; |
971 | } | 963 | } |
972 | 964 |
security/security.c
1 | /* | 1 | /* |
2 | * Security plug functions | 2 | * Security plug functions |
3 | * | 3 | * |
4 | * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> | 4 | * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> |
5 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> | 5 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> |
6 | * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> | 6 | * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/security.h> | 18 | #include <linux/security.h> |
19 | #include <linux/ima.h> | 19 | #include <linux/ima.h> |
20 | 20 | ||
21 | /* Boot-time LSM user choice */ | 21 | /* Boot-time LSM user choice */ |
22 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | 22 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = |
23 | CONFIG_DEFAULT_SECURITY; | 23 | CONFIG_DEFAULT_SECURITY; |
24 | 24 | ||
25 | /* things that live in capability.c */ | 25 | /* things that live in capability.c */ |
26 | extern void __init security_fixup_ops(struct security_operations *ops); | 26 | extern void __init security_fixup_ops(struct security_operations *ops); |
27 | 27 | ||
28 | static struct security_operations *security_ops; | 28 | static struct security_operations *security_ops; |
29 | static struct security_operations default_security_ops = { | 29 | static struct security_operations default_security_ops = { |
30 | .name = "default", | 30 | .name = "default", |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static inline int __init verify(struct security_operations *ops) | 33 | static inline int __init verify(struct security_operations *ops) |
34 | { | 34 | { |
35 | /* verify the security_operations structure exists */ | 35 | /* verify the security_operations structure exists */ |
36 | if (!ops) | 36 | if (!ops) |
37 | return -EINVAL; | 37 | return -EINVAL; |
38 | security_fixup_ops(ops); | 38 | security_fixup_ops(ops); |
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | static void __init do_security_initcalls(void) | 42 | static void __init do_security_initcalls(void) |
43 | { | 43 | { |
44 | initcall_t *call; | 44 | initcall_t *call; |
45 | call = __security_initcall_start; | 45 | call = __security_initcall_start; |
46 | while (call < __security_initcall_end) { | 46 | while (call < __security_initcall_end) { |
47 | (*call) (); | 47 | (*call) (); |
48 | call++; | 48 | call++; |
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * security_init - initializes the security framework | 53 | * security_init - initializes the security framework |
54 | * | 54 | * |
55 | * This should be called early in the kernel initialization sequence. | 55 | * This should be called early in the kernel initialization sequence. |
56 | */ | 56 | */ |
57 | int __init security_init(void) | 57 | int __init security_init(void) |
58 | { | 58 | { |
59 | printk(KERN_INFO "Security Framework initialized\n"); | 59 | printk(KERN_INFO "Security Framework initialized\n"); |
60 | 60 | ||
61 | security_fixup_ops(&default_security_ops); | 61 | security_fixup_ops(&default_security_ops); |
62 | security_ops = &default_security_ops; | 62 | security_ops = &default_security_ops; |
63 | do_security_initcalls(); | 63 | do_security_initcalls(); |
64 | 64 | ||
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
68 | void reset_security_ops(void) | 68 | void reset_security_ops(void) |
69 | { | 69 | { |
70 | security_ops = &default_security_ops; | 70 | security_ops = &default_security_ops; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* Save user chosen LSM */ | 73 | /* Save user chosen LSM */ |
74 | static int __init choose_lsm(char *str) | 74 | static int __init choose_lsm(char *str) |
75 | { | 75 | { |
76 | strncpy(chosen_lsm, str, SECURITY_NAME_MAX); | 76 | strncpy(chosen_lsm, str, SECURITY_NAME_MAX); |
77 | return 1; | 77 | return 1; |
78 | } | 78 | } |
79 | __setup("security=", choose_lsm); | 79 | __setup("security=", choose_lsm); |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * security_module_enable - Load given security module on boot ? | 82 | * security_module_enable - Load given security module on boot ? |
83 | * @ops: a pointer to the struct security_operations that is to be checked. | 83 | * @ops: a pointer to the struct security_operations that is to be checked. |
84 | * | 84 | * |
85 | * Each LSM must pass this method before registering its own operations | 85 | * Each LSM must pass this method before registering its own operations |
86 | * to avoid security registration races. This method may also be used | 86 | * to avoid security registration races. This method may also be used |
87 | * to check if your LSM is currently loaded during kernel initialization. | 87 | * to check if your LSM is currently loaded during kernel initialization. |
88 | * | 88 | * |
89 | * Return true if: | 89 | * Return true if: |
90 | * -The passed LSM is the one chosen by user at boot time, | 90 | * -The passed LSM is the one chosen by user at boot time, |
91 | * -or the passed LSM is configured as the default and the user did not | 91 | * -or the passed LSM is configured as the default and the user did not |
92 | * choose an alternate LSM at boot time. | 92 | * choose an alternate LSM at boot time. |
93 | * Otherwise, return false. | 93 | * Otherwise, return false. |
94 | */ | 94 | */ |
95 | int __init security_module_enable(struct security_operations *ops) | 95 | int __init security_module_enable(struct security_operations *ops) |
96 | { | 96 | { |
97 | return !strcmp(ops->name, chosen_lsm); | 97 | return !strcmp(ops->name, chosen_lsm); |
98 | } | 98 | } |
99 | 99 | ||
100 | /** | 100 | /** |
101 | * register_security - registers a security framework with the kernel | 101 | * register_security - registers a security framework with the kernel |
102 | * @ops: a pointer to the struct security_options that is to be registered | 102 | * @ops: a pointer to the struct security_options that is to be registered |
103 | * | 103 | * |
104 | * This function allows a security module to register itself with the | 104 | * This function allows a security module to register itself with the |
105 | * kernel security subsystem. Some rudimentary checking is done on the @ops | 105 | * kernel security subsystem. Some rudimentary checking is done on the @ops |
106 | * value passed to this function. You'll need to check first if your LSM | 106 | * value passed to this function. You'll need to check first if your LSM |
107 | * is allowed to register its @ops by calling security_module_enable(@ops). | 107 | * is allowed to register its @ops by calling security_module_enable(@ops). |
108 | * | 108 | * |
109 | * If there is already a security module registered with the kernel, | 109 | * If there is already a security module registered with the kernel, |
110 | * an error will be returned. Otherwise %0 is returned on success. | 110 | * an error will be returned. Otherwise %0 is returned on success. |
111 | */ | 111 | */ |
112 | int __init register_security(struct security_operations *ops) | 112 | int __init register_security(struct security_operations *ops) |
113 | { | 113 | { |
114 | if (verify(ops)) { | 114 | if (verify(ops)) { |
115 | printk(KERN_DEBUG "%s could not verify " | 115 | printk(KERN_DEBUG "%s could not verify " |
116 | "security_operations structure.\n", __func__); | 116 | "security_operations structure.\n", __func__); |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | } | 118 | } |
119 | 119 | ||
120 | if (security_ops != &default_security_ops) | 120 | if (security_ops != &default_security_ops) |
121 | return -EAGAIN; | 121 | return -EAGAIN; |
122 | 122 | ||
123 | security_ops = ops; | 123 | security_ops = ops; |
124 | 124 | ||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* Security operations */ | 128 | /* Security operations */ |
129 | 129 | ||
130 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode) | 130 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode) |
131 | { | 131 | { |
132 | return security_ops->ptrace_access_check(child, mode); | 132 | return security_ops->ptrace_access_check(child, mode); |
133 | } | 133 | } |
134 | 134 | ||
135 | int security_ptrace_traceme(struct task_struct *parent) | 135 | int security_ptrace_traceme(struct task_struct *parent) |
136 | { | 136 | { |
137 | return security_ops->ptrace_traceme(parent); | 137 | return security_ops->ptrace_traceme(parent); |
138 | } | 138 | } |
139 | 139 | ||
140 | int security_capget(struct task_struct *target, | 140 | int security_capget(struct task_struct *target, |
141 | kernel_cap_t *effective, | 141 | kernel_cap_t *effective, |
142 | kernel_cap_t *inheritable, | 142 | kernel_cap_t *inheritable, |
143 | kernel_cap_t *permitted) | 143 | kernel_cap_t *permitted) |
144 | { | 144 | { |
145 | return security_ops->capget(target, effective, inheritable, permitted); | 145 | return security_ops->capget(target, effective, inheritable, permitted); |
146 | } | 146 | } |
147 | 147 | ||
148 | int security_capset(struct cred *new, const struct cred *old, | 148 | int security_capset(struct cred *new, const struct cred *old, |
149 | const kernel_cap_t *effective, | 149 | const kernel_cap_t *effective, |
150 | const kernel_cap_t *inheritable, | 150 | const kernel_cap_t *inheritable, |
151 | const kernel_cap_t *permitted) | 151 | const kernel_cap_t *permitted) |
152 | { | 152 | { |
153 | return security_ops->capset(new, old, | 153 | return security_ops->capset(new, old, |
154 | effective, inheritable, permitted); | 154 | effective, inheritable, permitted); |
155 | } | 155 | } |
156 | 156 | ||
157 | int security_capable(const struct cred *cred, struct user_namespace *ns, | 157 | int security_capable(const struct cred *cred, struct user_namespace *ns, |
158 | int cap) | 158 | int cap) |
159 | { | 159 | { |
160 | return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); | 160 | return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); |
161 | } | 161 | } |
162 | 162 | ||
163 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, | 163 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, |
164 | int cap) | 164 | int cap) |
165 | { | 165 | { |
166 | return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); | 166 | return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); |
167 | } | 167 | } |
168 | 168 | ||
169 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) | 169 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
170 | { | 170 | { |
171 | return security_ops->quotactl(cmds, type, id, sb); | 171 | return security_ops->quotactl(cmds, type, id, sb); |
172 | } | 172 | } |
173 | 173 | ||
174 | int security_quota_on(struct dentry *dentry) | 174 | int security_quota_on(struct dentry *dentry) |
175 | { | 175 | { |
176 | return security_ops->quota_on(dentry); | 176 | return security_ops->quota_on(dentry); |
177 | } | 177 | } |
178 | 178 | ||
179 | int security_syslog(int type) | 179 | int security_syslog(int type) |
180 | { | 180 | { |
181 | return security_ops->syslog(type); | 181 | return security_ops->syslog(type); |
182 | } | 182 | } |
183 | 183 | ||
184 | int security_settime(const struct timespec *ts, const struct timezone *tz) | 184 | int security_settime(const struct timespec *ts, const struct timezone *tz) |
185 | { | 185 | { |
186 | return security_ops->settime(ts, tz); | 186 | return security_ops->settime(ts, tz); |
187 | } | 187 | } |
188 | 188 | ||
189 | int security_vm_enough_memory(long pages) | 189 | int security_vm_enough_memory(long pages) |
190 | { | 190 | { |
191 | WARN_ON(current->mm == NULL); | 191 | WARN_ON(current->mm == NULL); |
192 | return security_ops->vm_enough_memory(current->mm, pages); | 192 | return security_ops->vm_enough_memory(current->mm, pages); |
193 | } | 193 | } |
194 | 194 | ||
195 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | 195 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) |
196 | { | 196 | { |
197 | WARN_ON(mm == NULL); | 197 | WARN_ON(mm == NULL); |
198 | return security_ops->vm_enough_memory(mm, pages); | 198 | return security_ops->vm_enough_memory(mm, pages); |
199 | } | 199 | } |
200 | 200 | ||
201 | int security_vm_enough_memory_kern(long pages) | 201 | int security_vm_enough_memory_kern(long pages) |
202 | { | 202 | { |
203 | /* If current->mm is a kernel thread then we will pass NULL, | 203 | /* If current->mm is a kernel thread then we will pass NULL, |
204 | for this specific case that is fine */ | 204 | for this specific case that is fine */ |
205 | return security_ops->vm_enough_memory(current->mm, pages); | 205 | return security_ops->vm_enough_memory(current->mm, pages); |
206 | } | 206 | } |
207 | 207 | ||
208 | int security_bprm_set_creds(struct linux_binprm *bprm) | 208 | int security_bprm_set_creds(struct linux_binprm *bprm) |
209 | { | 209 | { |
210 | return security_ops->bprm_set_creds(bprm); | 210 | return security_ops->bprm_set_creds(bprm); |
211 | } | 211 | } |
212 | 212 | ||
213 | int security_bprm_check(struct linux_binprm *bprm) | 213 | int security_bprm_check(struct linux_binprm *bprm) |
214 | { | 214 | { |
215 | int ret; | 215 | int ret; |
216 | 216 | ||
217 | ret = security_ops->bprm_check_security(bprm); | 217 | ret = security_ops->bprm_check_security(bprm); |
218 | if (ret) | 218 | if (ret) |
219 | return ret; | 219 | return ret; |
220 | return ima_bprm_check(bprm); | 220 | return ima_bprm_check(bprm); |
221 | } | 221 | } |
222 | 222 | ||
223 | void security_bprm_committing_creds(struct linux_binprm *bprm) | 223 | void security_bprm_committing_creds(struct linux_binprm *bprm) |
224 | { | 224 | { |
225 | security_ops->bprm_committing_creds(bprm); | 225 | security_ops->bprm_committing_creds(bprm); |
226 | } | 226 | } |
227 | 227 | ||
228 | void security_bprm_committed_creds(struct linux_binprm *bprm) | 228 | void security_bprm_committed_creds(struct linux_binprm *bprm) |
229 | { | 229 | { |
230 | security_ops->bprm_committed_creds(bprm); | 230 | security_ops->bprm_committed_creds(bprm); |
231 | } | 231 | } |
232 | 232 | ||
233 | int security_bprm_secureexec(struct linux_binprm *bprm) | 233 | int security_bprm_secureexec(struct linux_binprm *bprm) |
234 | { | 234 | { |
235 | return security_ops->bprm_secureexec(bprm); | 235 | return security_ops->bprm_secureexec(bprm); |
236 | } | 236 | } |
237 | 237 | ||
238 | int security_sb_alloc(struct super_block *sb) | 238 | int security_sb_alloc(struct super_block *sb) |
239 | { | 239 | { |
240 | return security_ops->sb_alloc_security(sb); | 240 | return security_ops->sb_alloc_security(sb); |
241 | } | 241 | } |
242 | 242 | ||
243 | void security_sb_free(struct super_block *sb) | 243 | void security_sb_free(struct super_block *sb) |
244 | { | 244 | { |
245 | security_ops->sb_free_security(sb); | 245 | security_ops->sb_free_security(sb); |
246 | } | 246 | } |
247 | 247 | ||
248 | int security_sb_copy_data(char *orig, char *copy) | 248 | int security_sb_copy_data(char *orig, char *copy) |
249 | { | 249 | { |
250 | return security_ops->sb_copy_data(orig, copy); | 250 | return security_ops->sb_copy_data(orig, copy); |
251 | } | 251 | } |
252 | EXPORT_SYMBOL(security_sb_copy_data); | 252 | EXPORT_SYMBOL(security_sb_copy_data); |
253 | 253 | ||
254 | int security_sb_remount(struct super_block *sb, void *data) | 254 | int security_sb_remount(struct super_block *sb, void *data) |
255 | { | 255 | { |
256 | return security_ops->sb_remount(sb, data); | 256 | return security_ops->sb_remount(sb, data); |
257 | } | 257 | } |
258 | 258 | ||
259 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data) | 259 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
260 | { | 260 | { |
261 | return security_ops->sb_kern_mount(sb, flags, data); | 261 | return security_ops->sb_kern_mount(sb, flags, data); |
262 | } | 262 | } |
263 | 263 | ||
264 | int security_sb_show_options(struct seq_file *m, struct super_block *sb) | 264 | int security_sb_show_options(struct seq_file *m, struct super_block *sb) |
265 | { | 265 | { |
266 | return security_ops->sb_show_options(m, sb); | 266 | return security_ops->sb_show_options(m, sb); |
267 | } | 267 | } |
268 | 268 | ||
269 | int security_sb_statfs(struct dentry *dentry) | 269 | int security_sb_statfs(struct dentry *dentry) |
270 | { | 270 | { |
271 | return security_ops->sb_statfs(dentry); | 271 | return security_ops->sb_statfs(dentry); |
272 | } | 272 | } |
273 | 273 | ||
274 | int security_sb_mount(char *dev_name, struct path *path, | 274 | int security_sb_mount(char *dev_name, struct path *path, |
275 | char *type, unsigned long flags, void *data) | 275 | char *type, unsigned long flags, void *data) |
276 | { | 276 | { |
277 | return security_ops->sb_mount(dev_name, path, type, flags, data); | 277 | return security_ops->sb_mount(dev_name, path, type, flags, data); |
278 | } | 278 | } |
279 | 279 | ||
280 | int security_sb_umount(struct vfsmount *mnt, int flags) | 280 | int security_sb_umount(struct vfsmount *mnt, int flags) |
281 | { | 281 | { |
282 | return security_ops->sb_umount(mnt, flags); | 282 | return security_ops->sb_umount(mnt, flags); |
283 | } | 283 | } |
284 | 284 | ||
285 | int security_sb_pivotroot(struct path *old_path, struct path *new_path) | 285 | int security_sb_pivotroot(struct path *old_path, struct path *new_path) |
286 | { | 286 | { |
287 | return security_ops->sb_pivotroot(old_path, new_path); | 287 | return security_ops->sb_pivotroot(old_path, new_path); |
288 | } | 288 | } |
289 | 289 | ||
290 | int security_sb_set_mnt_opts(struct super_block *sb, | 290 | int security_sb_set_mnt_opts(struct super_block *sb, |
291 | struct security_mnt_opts *opts) | 291 | struct security_mnt_opts *opts) |
292 | { | 292 | { |
293 | return security_ops->sb_set_mnt_opts(sb, opts); | 293 | return security_ops->sb_set_mnt_opts(sb, opts); |
294 | } | 294 | } |
295 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 295 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
296 | 296 | ||
297 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 297 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, |
298 | struct super_block *newsb) | 298 | struct super_block *newsb) |
299 | { | 299 | { |
300 | security_ops->sb_clone_mnt_opts(oldsb, newsb); | 300 | security_ops->sb_clone_mnt_opts(oldsb, newsb); |
301 | } | 301 | } |
302 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); | 302 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
303 | 303 | ||
304 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 304 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
305 | { | 305 | { |
306 | return security_ops->sb_parse_opts_str(options, opts); | 306 | return security_ops->sb_parse_opts_str(options, opts); |
307 | } | 307 | } |
308 | EXPORT_SYMBOL(security_sb_parse_opts_str); | 308 | EXPORT_SYMBOL(security_sb_parse_opts_str); |
309 | 309 | ||
310 | int security_inode_alloc(struct inode *inode) | 310 | int security_inode_alloc(struct inode *inode) |
311 | { | 311 | { |
312 | inode->i_security = NULL; | 312 | inode->i_security = NULL; |
313 | return security_ops->inode_alloc_security(inode); | 313 | return security_ops->inode_alloc_security(inode); |
314 | } | 314 | } |
315 | 315 | ||
316 | void security_inode_free(struct inode *inode) | 316 | void security_inode_free(struct inode *inode) |
317 | { | 317 | { |
318 | ima_inode_free(inode); | 318 | ima_inode_free(inode); |
319 | security_ops->inode_free_security(inode); | 319 | security_ops->inode_free_security(inode); |
320 | } | 320 | } |
321 | 321 | ||
322 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 322 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
323 | const struct qstr *qstr, char **name, | 323 | const struct qstr *qstr, char **name, |
324 | void **value, size_t *len) | 324 | void **value, size_t *len) |
325 | { | 325 | { |
326 | if (unlikely(IS_PRIVATE(inode))) | 326 | if (unlikely(IS_PRIVATE(inode))) |
327 | return -EOPNOTSUPP; | 327 | return -EOPNOTSUPP; |
328 | return security_ops->inode_init_security(inode, dir, qstr, name, value, | 328 | return security_ops->inode_init_security(inode, dir, qstr, name, value, |
329 | len); | 329 | len); |
330 | } | 330 | } |
331 | EXPORT_SYMBOL(security_inode_init_security); | 331 | EXPORT_SYMBOL(security_inode_init_security); |
332 | 332 | ||
333 | #ifdef CONFIG_SECURITY_PATH | 333 | #ifdef CONFIG_SECURITY_PATH |
334 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, | 334 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, |
335 | unsigned int dev) | 335 | unsigned int dev) |
336 | { | 336 | { |
337 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) | 337 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
338 | return 0; | 338 | return 0; |
339 | return security_ops->path_mknod(dir, dentry, mode, dev); | 339 | return security_ops->path_mknod(dir, dentry, mode, dev); |
340 | } | 340 | } |
341 | EXPORT_SYMBOL(security_path_mknod); | 341 | EXPORT_SYMBOL(security_path_mknod); |
342 | 342 | ||
343 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode) | 343 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode) |
344 | { | 344 | { |
345 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) | 345 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
346 | return 0; | 346 | return 0; |
347 | return security_ops->path_mkdir(dir, dentry, mode); | 347 | return security_ops->path_mkdir(dir, dentry, mode); |
348 | } | 348 | } |
349 | EXPORT_SYMBOL(security_path_mkdir); | 349 | EXPORT_SYMBOL(security_path_mkdir); |
350 | 350 | ||
351 | int security_path_rmdir(struct path *dir, struct dentry *dentry) | 351 | int security_path_rmdir(struct path *dir, struct dentry *dentry) |
352 | { | 352 | { |
353 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) | 353 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
354 | return 0; | 354 | return 0; |
355 | return security_ops->path_rmdir(dir, dentry); | 355 | return security_ops->path_rmdir(dir, dentry); |
356 | } | 356 | } |
357 | 357 | ||
358 | int security_path_unlink(struct path *dir, struct dentry *dentry) | 358 | int security_path_unlink(struct path *dir, struct dentry *dentry) |
359 | { | 359 | { |
360 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) | 360 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
361 | return 0; | 361 | return 0; |
362 | return security_ops->path_unlink(dir, dentry); | 362 | return security_ops->path_unlink(dir, dentry); |
363 | } | 363 | } |
364 | EXPORT_SYMBOL(security_path_unlink); | 364 | EXPORT_SYMBOL(security_path_unlink); |
365 | 365 | ||
366 | int security_path_symlink(struct path *dir, struct dentry *dentry, | 366 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
367 | const char *old_name) | 367 | const char *old_name) |
368 | { | 368 | { |
369 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) | 369 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
370 | return 0; | 370 | return 0; |
371 | return security_ops->path_symlink(dir, dentry, old_name); | 371 | return security_ops->path_symlink(dir, dentry, old_name); |
372 | } | 372 | } |
373 | 373 | ||
374 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | 374 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, |
375 | struct dentry *new_dentry) | 375 | struct dentry *new_dentry) |
376 | { | 376 | { |
377 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) | 377 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) |
378 | return 0; | 378 | return 0; |
379 | return security_ops->path_link(old_dentry, new_dir, new_dentry); | 379 | return security_ops->path_link(old_dentry, new_dir, new_dentry); |
380 | } | 380 | } |
381 | 381 | ||
382 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | 382 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, |
383 | struct path *new_dir, struct dentry *new_dentry) | 383 | struct path *new_dir, struct dentry *new_dentry) |
384 | { | 384 | { |
385 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | 385 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || |
386 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | 386 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) |
387 | return 0; | 387 | return 0; |
388 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | 388 | return security_ops->path_rename(old_dir, old_dentry, new_dir, |
389 | new_dentry); | 389 | new_dentry); |
390 | } | 390 | } |
391 | EXPORT_SYMBOL(security_path_rename); | 391 | EXPORT_SYMBOL(security_path_rename); |
392 | 392 | ||
393 | int security_path_truncate(struct path *path) | 393 | int security_path_truncate(struct path *path) |
394 | { | 394 | { |
395 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 395 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) |
396 | return 0; | 396 | return 0; |
397 | return security_ops->path_truncate(path); | 397 | return security_ops->path_truncate(path); |
398 | } | 398 | } |
399 | 399 | ||
400 | int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | 400 | int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, |
401 | mode_t mode) | 401 | mode_t mode) |
402 | { | 402 | { |
403 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 403 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
404 | return 0; | 404 | return 0; |
405 | return security_ops->path_chmod(dentry, mnt, mode); | 405 | return security_ops->path_chmod(dentry, mnt, mode); |
406 | } | 406 | } |
407 | 407 | ||
408 | int security_path_chown(struct path *path, uid_t uid, gid_t gid) | 408 | int security_path_chown(struct path *path, uid_t uid, gid_t gid) |
409 | { | 409 | { |
410 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 410 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) |
411 | return 0; | 411 | return 0; |
412 | return security_ops->path_chown(path, uid, gid); | 412 | return security_ops->path_chown(path, uid, gid); |
413 | } | 413 | } |
414 | 414 | ||
415 | int security_path_chroot(struct path *path) | 415 | int security_path_chroot(struct path *path) |
416 | { | 416 | { |
417 | return security_ops->path_chroot(path); | 417 | return security_ops->path_chroot(path); |
418 | } | 418 | } |
419 | #endif | 419 | #endif |
420 | 420 | ||
421 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) | 421 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) |
422 | { | 422 | { |
423 | if (unlikely(IS_PRIVATE(dir))) | 423 | if (unlikely(IS_PRIVATE(dir))) |
424 | return 0; | 424 | return 0; |
425 | return security_ops->inode_create(dir, dentry, mode); | 425 | return security_ops->inode_create(dir, dentry, mode); |
426 | } | 426 | } |
427 | EXPORT_SYMBOL_GPL(security_inode_create); | 427 | EXPORT_SYMBOL_GPL(security_inode_create); |
428 | 428 | ||
429 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, | 429 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, |
430 | struct dentry *new_dentry) | 430 | struct dentry *new_dentry) |
431 | { | 431 | { |
432 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) | 432 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) |
433 | return 0; | 433 | return 0; |
434 | return security_ops->inode_link(old_dentry, dir, new_dentry); | 434 | return security_ops->inode_link(old_dentry, dir, new_dentry); |
435 | } | 435 | } |
436 | 436 | ||
437 | int security_inode_unlink(struct inode *dir, struct dentry *dentry) | 437 | int security_inode_unlink(struct inode *dir, struct dentry *dentry) |
438 | { | 438 | { |
439 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 439 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
440 | return 0; | 440 | return 0; |
441 | return security_ops->inode_unlink(dir, dentry); | 441 | return security_ops->inode_unlink(dir, dentry); |
442 | } | 442 | } |
443 | 443 | ||
444 | int security_inode_symlink(struct inode *dir, struct dentry *dentry, | 444 | int security_inode_symlink(struct inode *dir, struct dentry *dentry, |
445 | const char *old_name) | 445 | const char *old_name) |
446 | { | 446 | { |
447 | if (unlikely(IS_PRIVATE(dir))) | 447 | if (unlikely(IS_PRIVATE(dir))) |
448 | return 0; | 448 | return 0; |
449 | return security_ops->inode_symlink(dir, dentry, old_name); | 449 | return security_ops->inode_symlink(dir, dentry, old_name); |
450 | } | 450 | } |
451 | 451 | ||
452 | int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 452 | int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
453 | { | 453 | { |
454 | if (unlikely(IS_PRIVATE(dir))) | 454 | if (unlikely(IS_PRIVATE(dir))) |
455 | return 0; | 455 | return 0; |
456 | return security_ops->inode_mkdir(dir, dentry, mode); | 456 | return security_ops->inode_mkdir(dir, dentry, mode); |
457 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(security_inode_mkdir); | 458 | EXPORT_SYMBOL_GPL(security_inode_mkdir); |
459 | 459 | ||
460 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry) | 460 | int security_inode_rmdir(struct inode *dir, struct dentry *dentry) |
461 | { | 461 | { |
462 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 462 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
463 | return 0; | 463 | return 0; |
464 | return security_ops->inode_rmdir(dir, dentry); | 464 | return security_ops->inode_rmdir(dir, dentry); |
465 | } | 465 | } |
466 | 466 | ||
467 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | 467 | int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) |
468 | { | 468 | { |
469 | if (unlikely(IS_PRIVATE(dir))) | 469 | if (unlikely(IS_PRIVATE(dir))) |
470 | return 0; | 470 | return 0; |
471 | return security_ops->inode_mknod(dir, dentry, mode, dev); | 471 | return security_ops->inode_mknod(dir, dentry, mode, dev); |
472 | } | 472 | } |
473 | 473 | ||
474 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | 474 | int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, |
475 | struct inode *new_dir, struct dentry *new_dentry) | 475 | struct inode *new_dir, struct dentry *new_dentry) |
476 | { | 476 | { |
477 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | 477 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || |
478 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | 478 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) |
479 | return 0; | 479 | return 0; |
480 | return security_ops->inode_rename(old_dir, old_dentry, | 480 | return security_ops->inode_rename(old_dir, old_dentry, |
481 | new_dir, new_dentry); | 481 | new_dir, new_dentry); |
482 | } | 482 | } |
483 | 483 | ||
484 | int security_inode_readlink(struct dentry *dentry) | 484 | int security_inode_readlink(struct dentry *dentry) |
485 | { | 485 | { |
486 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 486 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
487 | return 0; | 487 | return 0; |
488 | return security_ops->inode_readlink(dentry); | 488 | return security_ops->inode_readlink(dentry); |
489 | } | 489 | } |
490 | 490 | ||
491 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd) | 491 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd) |
492 | { | 492 | { |
493 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 493 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
494 | return 0; | 494 | return 0; |
495 | return security_ops->inode_follow_link(dentry, nd); | 495 | return security_ops->inode_follow_link(dentry, nd); |
496 | } | 496 | } |
497 | 497 | ||
498 | int security_inode_permission(struct inode *inode, int mask) | 498 | int security_inode_permission(struct inode *inode, int mask) |
499 | { | 499 | { |
500 | if (unlikely(IS_PRIVATE(inode))) | 500 | if (unlikely(IS_PRIVATE(inode))) |
501 | return 0; | 501 | return 0; |
502 | return security_ops->inode_permission(inode, mask); | 502 | return security_ops->inode_permission(inode, mask); |
503 | } | 503 | } |
504 | 504 | ||
505 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr) | 505 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr) |
506 | { | 506 | { |
507 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 507 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
508 | return 0; | 508 | return 0; |
509 | return security_ops->inode_setattr(dentry, attr); | 509 | return security_ops->inode_setattr(dentry, attr); |
510 | } | 510 | } |
511 | EXPORT_SYMBOL_GPL(security_inode_setattr); | 511 | EXPORT_SYMBOL_GPL(security_inode_setattr); |
512 | 512 | ||
513 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 513 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
514 | { | 514 | { |
515 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 515 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
516 | return 0; | 516 | return 0; |
517 | return security_ops->inode_getattr(mnt, dentry); | 517 | return security_ops->inode_getattr(mnt, dentry); |
518 | } | 518 | } |
519 | 519 | ||
520 | int security_inode_setxattr(struct dentry *dentry, const char *name, | 520 | int security_inode_setxattr(struct dentry *dentry, const char *name, |
521 | const void *value, size_t size, int flags) | 521 | const void *value, size_t size, int flags) |
522 | { | 522 | { |
523 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 523 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
524 | return 0; | 524 | return 0; |
525 | return security_ops->inode_setxattr(dentry, name, value, size, flags); | 525 | return security_ops->inode_setxattr(dentry, name, value, size, flags); |
526 | } | 526 | } |
527 | 527 | ||
528 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, | 528 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, |
529 | const void *value, size_t size, int flags) | 529 | const void *value, size_t size, int flags) |
530 | { | 530 | { |
531 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 531 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
532 | return; | 532 | return; |
533 | security_ops->inode_post_setxattr(dentry, name, value, size, flags); | 533 | security_ops->inode_post_setxattr(dentry, name, value, size, flags); |
534 | } | 534 | } |
535 | 535 | ||
536 | int security_inode_getxattr(struct dentry *dentry, const char *name) | 536 | int security_inode_getxattr(struct dentry *dentry, const char *name) |
537 | { | 537 | { |
538 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 538 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
539 | return 0; | 539 | return 0; |
540 | return security_ops->inode_getxattr(dentry, name); | 540 | return security_ops->inode_getxattr(dentry, name); |
541 | } | 541 | } |
542 | 542 | ||
543 | int security_inode_listxattr(struct dentry *dentry) | 543 | int security_inode_listxattr(struct dentry *dentry) |
544 | { | 544 | { |
545 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 545 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
546 | return 0; | 546 | return 0; |
547 | return security_ops->inode_listxattr(dentry); | 547 | return security_ops->inode_listxattr(dentry); |
548 | } | 548 | } |
549 | 549 | ||
550 | int security_inode_removexattr(struct dentry *dentry, const char *name) | 550 | int security_inode_removexattr(struct dentry *dentry, const char *name) |
551 | { | 551 | { |
552 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | 552 | if (unlikely(IS_PRIVATE(dentry->d_inode))) |
553 | return 0; | 553 | return 0; |
554 | return security_ops->inode_removexattr(dentry, name); | 554 | return security_ops->inode_removexattr(dentry, name); |
555 | } | 555 | } |
556 | 556 | ||
557 | int security_inode_need_killpriv(struct dentry *dentry) | 557 | int security_inode_need_killpriv(struct dentry *dentry) |
558 | { | 558 | { |
559 | return security_ops->inode_need_killpriv(dentry); | 559 | return security_ops->inode_need_killpriv(dentry); |
560 | } | 560 | } |
561 | 561 | ||
562 | int security_inode_killpriv(struct dentry *dentry) | 562 | int security_inode_killpriv(struct dentry *dentry) |
563 | { | 563 | { |
564 | return security_ops->inode_killpriv(dentry); | 564 | return security_ops->inode_killpriv(dentry); |
565 | } | 565 | } |
566 | 566 | ||
567 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) | 567 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
568 | { | 568 | { |
569 | if (unlikely(IS_PRIVATE(inode))) | 569 | if (unlikely(IS_PRIVATE(inode))) |
570 | return -EOPNOTSUPP; | 570 | return -EOPNOTSUPP; |
571 | return security_ops->inode_getsecurity(inode, name, buffer, alloc); | 571 | return security_ops->inode_getsecurity(inode, name, buffer, alloc); |
572 | } | 572 | } |
573 | 573 | ||
574 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) | 574 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) |
575 | { | 575 | { |
576 | if (unlikely(IS_PRIVATE(inode))) | 576 | if (unlikely(IS_PRIVATE(inode))) |
577 | return -EOPNOTSUPP; | 577 | return -EOPNOTSUPP; |
578 | return security_ops->inode_setsecurity(inode, name, value, size, flags); | 578 | return security_ops->inode_setsecurity(inode, name, value, size, flags); |
579 | } | 579 | } |
580 | 580 | ||
581 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) | 581 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) |
582 | { | 582 | { |
583 | if (unlikely(IS_PRIVATE(inode))) | 583 | if (unlikely(IS_PRIVATE(inode))) |
584 | return 0; | 584 | return 0; |
585 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); | 585 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); |
586 | } | 586 | } |
587 | 587 | ||
588 | void security_inode_getsecid(const struct inode *inode, u32 *secid) | 588 | void security_inode_getsecid(const struct inode *inode, u32 *secid) |
589 | { | 589 | { |
590 | security_ops->inode_getsecid(inode, secid); | 590 | security_ops->inode_getsecid(inode, secid); |
591 | } | 591 | } |
592 | 592 | ||
593 | int security_file_permission(struct file *file, int mask) | 593 | int security_file_permission(struct file *file, int mask) |
594 | { | 594 | { |
595 | int ret; | 595 | int ret; |
596 | 596 | ||
597 | ret = security_ops->file_permission(file, mask); | 597 | ret = security_ops->file_permission(file, mask); |
598 | if (ret) | 598 | if (ret) |
599 | return ret; | 599 | return ret; |
600 | 600 | ||
601 | return fsnotify_perm(file, mask); | 601 | return fsnotify_perm(file, mask); |
602 | } | 602 | } |
603 | 603 | ||
604 | int security_file_alloc(struct file *file) | 604 | int security_file_alloc(struct file *file) |
605 | { | 605 | { |
606 | return security_ops->file_alloc_security(file); | 606 | return security_ops->file_alloc_security(file); |
607 | } | 607 | } |
608 | 608 | ||
609 | void security_file_free(struct file *file) | 609 | void security_file_free(struct file *file) |
610 | { | 610 | { |
611 | security_ops->file_free_security(file); | 611 | security_ops->file_free_security(file); |
612 | } | 612 | } |
613 | 613 | ||
614 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 614 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
615 | { | 615 | { |
616 | return security_ops->file_ioctl(file, cmd, arg); | 616 | return security_ops->file_ioctl(file, cmd, arg); |
617 | } | 617 | } |
618 | 618 | ||
619 | int security_file_mmap(struct file *file, unsigned long reqprot, | 619 | int security_file_mmap(struct file *file, unsigned long reqprot, |
620 | unsigned long prot, unsigned long flags, | 620 | unsigned long prot, unsigned long flags, |
621 | unsigned long addr, unsigned long addr_only) | 621 | unsigned long addr, unsigned long addr_only) |
622 | { | 622 | { |
623 | int ret; | 623 | int ret; |
624 | 624 | ||
625 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | 625 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); |
626 | if (ret) | 626 | if (ret) |
627 | return ret; | 627 | return ret; |
628 | return ima_file_mmap(file, prot); | 628 | return ima_file_mmap(file, prot); |
629 | } | 629 | } |
630 | 630 | ||
631 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 631 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
632 | unsigned long prot) | 632 | unsigned long prot) |
633 | { | 633 | { |
634 | return security_ops->file_mprotect(vma, reqprot, prot); | 634 | return security_ops->file_mprotect(vma, reqprot, prot); |
635 | } | 635 | } |
636 | 636 | ||
637 | int security_file_lock(struct file *file, unsigned int cmd) | 637 | int security_file_lock(struct file *file, unsigned int cmd) |
638 | { | 638 | { |
639 | return security_ops->file_lock(file, cmd); | 639 | return security_ops->file_lock(file, cmd); |
640 | } | 640 | } |
641 | 641 | ||
642 | int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) | 642 | int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) |
643 | { | 643 | { |
644 | return security_ops->file_fcntl(file, cmd, arg); | 644 | return security_ops->file_fcntl(file, cmd, arg); |
645 | } | 645 | } |
646 | 646 | ||
647 | int security_file_set_fowner(struct file *file) | 647 | int security_file_set_fowner(struct file *file) |
648 | { | 648 | { |
649 | return security_ops->file_set_fowner(file); | 649 | return security_ops->file_set_fowner(file); |
650 | } | 650 | } |
651 | 651 | ||
652 | int security_file_send_sigiotask(struct task_struct *tsk, | 652 | int security_file_send_sigiotask(struct task_struct *tsk, |
653 | struct fown_struct *fown, int sig) | 653 | struct fown_struct *fown, int sig) |
654 | { | 654 | { |
655 | return security_ops->file_send_sigiotask(tsk, fown, sig); | 655 | return security_ops->file_send_sigiotask(tsk, fown, sig); |
656 | } | 656 | } |
657 | 657 | ||
658 | int security_file_receive(struct file *file) | 658 | int security_file_receive(struct file *file) |
659 | { | 659 | { |
660 | return security_ops->file_receive(file); | 660 | return security_ops->file_receive(file); |
661 | } | 661 | } |
662 | 662 | ||
663 | int security_dentry_open(struct file *file, const struct cred *cred) | 663 | int security_dentry_open(struct file *file, const struct cred *cred) |
664 | { | 664 | { |
665 | int ret; | 665 | int ret; |
666 | 666 | ||
667 | ret = security_ops->dentry_open(file, cred); | 667 | ret = security_ops->dentry_open(file, cred); |
668 | if (ret) | 668 | if (ret) |
669 | return ret; | 669 | return ret; |
670 | 670 | ||
671 | return fsnotify_perm(file, MAY_OPEN); | 671 | return fsnotify_perm(file, MAY_OPEN); |
672 | } | 672 | } |
673 | 673 | ||
674 | int security_task_create(unsigned long clone_flags) | 674 | int security_task_create(unsigned long clone_flags) |
675 | { | 675 | { |
676 | return security_ops->task_create(clone_flags); | 676 | return security_ops->task_create(clone_flags); |
677 | } | 677 | } |
678 | 678 | ||
679 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 679 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
680 | { | 680 | { |
681 | return security_ops->cred_alloc_blank(cred, gfp); | 681 | return security_ops->cred_alloc_blank(cred, gfp); |
682 | } | 682 | } |
683 | 683 | ||
684 | void security_cred_free(struct cred *cred) | 684 | void security_cred_free(struct cred *cred) |
685 | { | 685 | { |
686 | security_ops->cred_free(cred); | 686 | security_ops->cred_free(cred); |
687 | } | 687 | } |
688 | 688 | ||
689 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) | 689 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) |
690 | { | 690 | { |
691 | return security_ops->cred_prepare(new, old, gfp); | 691 | return security_ops->cred_prepare(new, old, gfp); |
692 | } | 692 | } |
693 | 693 | ||
694 | void security_transfer_creds(struct cred *new, const struct cred *old) | 694 | void security_transfer_creds(struct cred *new, const struct cred *old) |
695 | { | 695 | { |
696 | security_ops->cred_transfer(new, old); | 696 | security_ops->cred_transfer(new, old); |
697 | } | 697 | } |
698 | 698 | ||
699 | int security_kernel_act_as(struct cred *new, u32 secid) | 699 | int security_kernel_act_as(struct cred *new, u32 secid) |
700 | { | 700 | { |
701 | return security_ops->kernel_act_as(new, secid); | 701 | return security_ops->kernel_act_as(new, secid); |
702 | } | 702 | } |
703 | 703 | ||
704 | int security_kernel_create_files_as(struct cred *new, struct inode *inode) | 704 | int security_kernel_create_files_as(struct cred *new, struct inode *inode) |
705 | { | 705 | { |
706 | return security_ops->kernel_create_files_as(new, inode); | 706 | return security_ops->kernel_create_files_as(new, inode); |
707 | } | 707 | } |
708 | 708 | ||
709 | int security_kernel_module_request(char *kmod_name) | 709 | int security_kernel_module_request(char *kmod_name) |
710 | { | 710 | { |
711 | return security_ops->kernel_module_request(kmod_name); | 711 | return security_ops->kernel_module_request(kmod_name); |
712 | } | 712 | } |
713 | 713 | ||
714 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 714 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
715 | int flags) | 715 | int flags) |
716 | { | 716 | { |
717 | return security_ops->task_fix_setuid(new, old, flags); | 717 | return security_ops->task_fix_setuid(new, old, flags); |
718 | } | 718 | } |
719 | 719 | ||
720 | int security_task_setpgid(struct task_struct *p, pid_t pgid) | 720 | int security_task_setpgid(struct task_struct *p, pid_t pgid) |
721 | { | 721 | { |
722 | return security_ops->task_setpgid(p, pgid); | 722 | return security_ops->task_setpgid(p, pgid); |
723 | } | 723 | } |
724 | 724 | ||
725 | int security_task_getpgid(struct task_struct *p) | 725 | int security_task_getpgid(struct task_struct *p) |
726 | { | 726 | { |
727 | return security_ops->task_getpgid(p); | 727 | return security_ops->task_getpgid(p); |
728 | } | 728 | } |
729 | 729 | ||
730 | int security_task_getsid(struct task_struct *p) | 730 | int security_task_getsid(struct task_struct *p) |
731 | { | 731 | { |
732 | return security_ops->task_getsid(p); | 732 | return security_ops->task_getsid(p); |
733 | } | 733 | } |
734 | 734 | ||
735 | void security_task_getsecid(struct task_struct *p, u32 *secid) | 735 | void security_task_getsecid(struct task_struct *p, u32 *secid) |
736 | { | 736 | { |
737 | security_ops->task_getsecid(p, secid); | 737 | security_ops->task_getsecid(p, secid); |
738 | } | 738 | } |
739 | EXPORT_SYMBOL(security_task_getsecid); | 739 | EXPORT_SYMBOL(security_task_getsecid); |
740 | 740 | ||
741 | int security_task_setnice(struct task_struct *p, int nice) | 741 | int security_task_setnice(struct task_struct *p, int nice) |
742 | { | 742 | { |
743 | return security_ops->task_setnice(p, nice); | 743 | return security_ops->task_setnice(p, nice); |
744 | } | 744 | } |
745 | 745 | ||
746 | int security_task_setioprio(struct task_struct *p, int ioprio) | 746 | int security_task_setioprio(struct task_struct *p, int ioprio) |
747 | { | 747 | { |
748 | return security_ops->task_setioprio(p, ioprio); | 748 | return security_ops->task_setioprio(p, ioprio); |
749 | } | 749 | } |
750 | 750 | ||
751 | int security_task_getioprio(struct task_struct *p) | 751 | int security_task_getioprio(struct task_struct *p) |
752 | { | 752 | { |
753 | return security_ops->task_getioprio(p); | 753 | return security_ops->task_getioprio(p); |
754 | } | 754 | } |
755 | 755 | ||
756 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, | 756 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, |
757 | struct rlimit *new_rlim) | 757 | struct rlimit *new_rlim) |
758 | { | 758 | { |
759 | return security_ops->task_setrlimit(p, resource, new_rlim); | 759 | return security_ops->task_setrlimit(p, resource, new_rlim); |
760 | } | 760 | } |
761 | 761 | ||
762 | int security_task_setscheduler(struct task_struct *p) | 762 | int security_task_setscheduler(struct task_struct *p) |
763 | { | 763 | { |
764 | return security_ops->task_setscheduler(p); | 764 | return security_ops->task_setscheduler(p); |
765 | } | 765 | } |
766 | 766 | ||
767 | int security_task_getscheduler(struct task_struct *p) | 767 | int security_task_getscheduler(struct task_struct *p) |
768 | { | 768 | { |
769 | return security_ops->task_getscheduler(p); | 769 | return security_ops->task_getscheduler(p); |
770 | } | 770 | } |
771 | 771 | ||
772 | int security_task_movememory(struct task_struct *p) | 772 | int security_task_movememory(struct task_struct *p) |
773 | { | 773 | { |
774 | return security_ops->task_movememory(p); | 774 | return security_ops->task_movememory(p); |
775 | } | 775 | } |
776 | 776 | ||
777 | int security_task_kill(struct task_struct *p, struct siginfo *info, | 777 | int security_task_kill(struct task_struct *p, struct siginfo *info, |
778 | int sig, u32 secid) | 778 | int sig, u32 secid) |
779 | { | 779 | { |
780 | return security_ops->task_kill(p, info, sig, secid); | 780 | return security_ops->task_kill(p, info, sig, secid); |
781 | } | 781 | } |
782 | 782 | ||
783 | int security_task_wait(struct task_struct *p) | 783 | int security_task_wait(struct task_struct *p) |
784 | { | 784 | { |
785 | return security_ops->task_wait(p); | 785 | return security_ops->task_wait(p); |
786 | } | 786 | } |
787 | 787 | ||
788 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 788 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
789 | unsigned long arg4, unsigned long arg5) | 789 | unsigned long arg4, unsigned long arg5) |
790 | { | 790 | { |
791 | return security_ops->task_prctl(option, arg2, arg3, arg4, arg5); | 791 | return security_ops->task_prctl(option, arg2, arg3, arg4, arg5); |
792 | } | 792 | } |
793 | 793 | ||
794 | void security_task_to_inode(struct task_struct *p, struct inode *inode) | 794 | void security_task_to_inode(struct task_struct *p, struct inode *inode) |
795 | { | 795 | { |
796 | security_ops->task_to_inode(p, inode); | 796 | security_ops->task_to_inode(p, inode); |
797 | } | 797 | } |
798 | 798 | ||
799 | int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | 799 | int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) |
800 | { | 800 | { |
801 | return security_ops->ipc_permission(ipcp, flag); | 801 | return security_ops->ipc_permission(ipcp, flag); |
802 | } | 802 | } |
803 | 803 | ||
804 | void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | 804 | void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) |
805 | { | 805 | { |
806 | security_ops->ipc_getsecid(ipcp, secid); | 806 | security_ops->ipc_getsecid(ipcp, secid); |
807 | } | 807 | } |
808 | 808 | ||
809 | int security_msg_msg_alloc(struct msg_msg *msg) | 809 | int security_msg_msg_alloc(struct msg_msg *msg) |
810 | { | 810 | { |
811 | return security_ops->msg_msg_alloc_security(msg); | 811 | return security_ops->msg_msg_alloc_security(msg); |
812 | } | 812 | } |
813 | 813 | ||
814 | void security_msg_msg_free(struct msg_msg *msg) | 814 | void security_msg_msg_free(struct msg_msg *msg) |
815 | { | 815 | { |
816 | security_ops->msg_msg_free_security(msg); | 816 | security_ops->msg_msg_free_security(msg); |
817 | } | 817 | } |
818 | 818 | ||
819 | int security_msg_queue_alloc(struct msg_queue *msq) | 819 | int security_msg_queue_alloc(struct msg_queue *msq) |
820 | { | 820 | { |
821 | return security_ops->msg_queue_alloc_security(msq); | 821 | return security_ops->msg_queue_alloc_security(msq); |
822 | } | 822 | } |
823 | 823 | ||
824 | void security_msg_queue_free(struct msg_queue *msq) | 824 | void security_msg_queue_free(struct msg_queue *msq) |
825 | { | 825 | { |
826 | security_ops->msg_queue_free_security(msq); | 826 | security_ops->msg_queue_free_security(msq); |
827 | } | 827 | } |
828 | 828 | ||
829 | int security_msg_queue_associate(struct msg_queue *msq, int msqflg) | 829 | int security_msg_queue_associate(struct msg_queue *msq, int msqflg) |
830 | { | 830 | { |
831 | return security_ops->msg_queue_associate(msq, msqflg); | 831 | return security_ops->msg_queue_associate(msq, msqflg); |
832 | } | 832 | } |
833 | 833 | ||
834 | int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) | 834 | int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) |
835 | { | 835 | { |
836 | return security_ops->msg_queue_msgctl(msq, cmd); | 836 | return security_ops->msg_queue_msgctl(msq, cmd); |
837 | } | 837 | } |
838 | 838 | ||
839 | int security_msg_queue_msgsnd(struct msg_queue *msq, | 839 | int security_msg_queue_msgsnd(struct msg_queue *msq, |
840 | struct msg_msg *msg, int msqflg) | 840 | struct msg_msg *msg, int msqflg) |
841 | { | 841 | { |
842 | return security_ops->msg_queue_msgsnd(msq, msg, msqflg); | 842 | return security_ops->msg_queue_msgsnd(msq, msg, msqflg); |
843 | } | 843 | } |
844 | 844 | ||
845 | int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | 845 | int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, |
846 | struct task_struct *target, long type, int mode) | 846 | struct task_struct *target, long type, int mode) |
847 | { | 847 | { |
848 | return security_ops->msg_queue_msgrcv(msq, msg, target, type, mode); | 848 | return security_ops->msg_queue_msgrcv(msq, msg, target, type, mode); |
849 | } | 849 | } |
850 | 850 | ||
851 | int security_shm_alloc(struct shmid_kernel *shp) | 851 | int security_shm_alloc(struct shmid_kernel *shp) |
852 | { | 852 | { |
853 | return security_ops->shm_alloc_security(shp); | 853 | return security_ops->shm_alloc_security(shp); |
854 | } | 854 | } |
855 | 855 | ||
856 | void security_shm_free(struct shmid_kernel *shp) | 856 | void security_shm_free(struct shmid_kernel *shp) |
857 | { | 857 | { |
858 | security_ops->shm_free_security(shp); | 858 | security_ops->shm_free_security(shp); |
859 | } | 859 | } |
860 | 860 | ||
861 | int security_shm_associate(struct shmid_kernel *shp, int shmflg) | 861 | int security_shm_associate(struct shmid_kernel *shp, int shmflg) |
862 | { | 862 | { |
863 | return security_ops->shm_associate(shp, shmflg); | 863 | return security_ops->shm_associate(shp, shmflg); |
864 | } | 864 | } |
865 | 865 | ||
866 | int security_shm_shmctl(struct shmid_kernel *shp, int cmd) | 866 | int security_shm_shmctl(struct shmid_kernel *shp, int cmd) |
867 | { | 867 | { |
868 | return security_ops->shm_shmctl(shp, cmd); | 868 | return security_ops->shm_shmctl(shp, cmd); |
869 | } | 869 | } |
870 | 870 | ||
871 | int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg) | 871 | int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg) |
872 | { | 872 | { |
873 | return security_ops->shm_shmat(shp, shmaddr, shmflg); | 873 | return security_ops->shm_shmat(shp, shmaddr, shmflg); |
874 | } | 874 | } |
875 | 875 | ||
876 | int security_sem_alloc(struct sem_array *sma) | 876 | int security_sem_alloc(struct sem_array *sma) |
877 | { | 877 | { |
878 | return security_ops->sem_alloc_security(sma); | 878 | return security_ops->sem_alloc_security(sma); |
879 | } | 879 | } |
880 | 880 | ||
881 | void security_sem_free(struct sem_array *sma) | 881 | void security_sem_free(struct sem_array *sma) |
882 | { | 882 | { |
883 | security_ops->sem_free_security(sma); | 883 | security_ops->sem_free_security(sma); |
884 | } | 884 | } |
885 | 885 | ||
886 | int security_sem_associate(struct sem_array *sma, int semflg) | 886 | int security_sem_associate(struct sem_array *sma, int semflg) |
887 | { | 887 | { |
888 | return security_ops->sem_associate(sma, semflg); | 888 | return security_ops->sem_associate(sma, semflg); |
889 | } | 889 | } |
890 | 890 | ||
891 | int security_sem_semctl(struct sem_array *sma, int cmd) | 891 | int security_sem_semctl(struct sem_array *sma, int cmd) |
892 | { | 892 | { |
893 | return security_ops->sem_semctl(sma, cmd); | 893 | return security_ops->sem_semctl(sma, cmd); |
894 | } | 894 | } |
895 | 895 | ||
896 | int security_sem_semop(struct sem_array *sma, struct sembuf *sops, | 896 | int security_sem_semop(struct sem_array *sma, struct sembuf *sops, |
897 | unsigned nsops, int alter) | 897 | unsigned nsops, int alter) |
898 | { | 898 | { |
899 | return security_ops->sem_semop(sma, sops, nsops, alter); | 899 | return security_ops->sem_semop(sma, sops, nsops, alter); |
900 | } | 900 | } |
901 | 901 | ||
902 | void security_d_instantiate(struct dentry *dentry, struct inode *inode) | 902 | void security_d_instantiate(struct dentry *dentry, struct inode *inode) |
903 | { | 903 | { |
904 | if (unlikely(inode && IS_PRIVATE(inode))) | 904 | if (unlikely(inode && IS_PRIVATE(inode))) |
905 | return; | 905 | return; |
906 | security_ops->d_instantiate(dentry, inode); | 906 | security_ops->d_instantiate(dentry, inode); |
907 | } | 907 | } |
908 | EXPORT_SYMBOL(security_d_instantiate); | 908 | EXPORT_SYMBOL(security_d_instantiate); |
909 | 909 | ||
910 | int security_getprocattr(struct task_struct *p, char *name, char **value) | 910 | int security_getprocattr(struct task_struct *p, char *name, char **value) |
911 | { | 911 | { |
912 | return security_ops->getprocattr(p, name, value); | 912 | return security_ops->getprocattr(p, name, value); |
913 | } | 913 | } |
914 | 914 | ||
915 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) | 915 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) |
916 | { | 916 | { |
917 | return security_ops->setprocattr(p, name, value, size); | 917 | return security_ops->setprocattr(p, name, value, size); |
918 | } | 918 | } |
919 | 919 | ||
920 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 920 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
921 | { | 921 | { |
922 | return security_ops->netlink_send(sk, skb); | 922 | return security_ops->netlink_send(sk, skb); |
923 | } | 923 | } |
924 | 924 | ||
925 | int security_netlink_recv(struct sk_buff *skb, int cap) | ||
926 | { | ||
927 | return security_ops->netlink_recv(skb, cap); | ||
928 | } | ||
929 | EXPORT_SYMBOL(security_netlink_recv); | ||
930 | |||
931 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 925 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
932 | { | 926 | { |
933 | return security_ops->secid_to_secctx(secid, secdata, seclen); | 927 | return security_ops->secid_to_secctx(secid, secdata, seclen); |
934 | } | 928 | } |
935 | EXPORT_SYMBOL(security_secid_to_secctx); | 929 | EXPORT_SYMBOL(security_secid_to_secctx); |
936 | 930 | ||
937 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 931 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
938 | { | 932 | { |
939 | return security_ops->secctx_to_secid(secdata, seclen, secid); | 933 | return security_ops->secctx_to_secid(secdata, seclen, secid); |
940 | } | 934 | } |
941 | EXPORT_SYMBOL(security_secctx_to_secid); | 935 | EXPORT_SYMBOL(security_secctx_to_secid); |
942 | 936 | ||
943 | void security_release_secctx(char *secdata, u32 seclen) | 937 | void security_release_secctx(char *secdata, u32 seclen) |
944 | { | 938 | { |
945 | security_ops->release_secctx(secdata, seclen); | 939 | security_ops->release_secctx(secdata, seclen); |
946 | } | 940 | } |
947 | EXPORT_SYMBOL(security_release_secctx); | 941 | EXPORT_SYMBOL(security_release_secctx); |
948 | 942 | ||
949 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | 943 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) |
950 | { | 944 | { |
951 | return security_ops->inode_notifysecctx(inode, ctx, ctxlen); | 945 | return security_ops->inode_notifysecctx(inode, ctx, ctxlen); |
952 | } | 946 | } |
953 | EXPORT_SYMBOL(security_inode_notifysecctx); | 947 | EXPORT_SYMBOL(security_inode_notifysecctx); |
954 | 948 | ||
955 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | 949 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) |
956 | { | 950 | { |
957 | return security_ops->inode_setsecctx(dentry, ctx, ctxlen); | 951 | return security_ops->inode_setsecctx(dentry, ctx, ctxlen); |
958 | } | 952 | } |
959 | EXPORT_SYMBOL(security_inode_setsecctx); | 953 | EXPORT_SYMBOL(security_inode_setsecctx); |
960 | 954 | ||
961 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | 955 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) |
962 | { | 956 | { |
963 | return security_ops->inode_getsecctx(inode, ctx, ctxlen); | 957 | return security_ops->inode_getsecctx(inode, ctx, ctxlen); |
964 | } | 958 | } |
965 | EXPORT_SYMBOL(security_inode_getsecctx); | 959 | EXPORT_SYMBOL(security_inode_getsecctx); |
966 | 960 | ||
967 | #ifdef CONFIG_SECURITY_NETWORK | 961 | #ifdef CONFIG_SECURITY_NETWORK |
968 | 962 | ||
969 | int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) | 963 | int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) |
970 | { | 964 | { |
971 | return security_ops->unix_stream_connect(sock, other, newsk); | 965 | return security_ops->unix_stream_connect(sock, other, newsk); |
972 | } | 966 | } |
973 | EXPORT_SYMBOL(security_unix_stream_connect); | 967 | EXPORT_SYMBOL(security_unix_stream_connect); |
974 | 968 | ||
975 | int security_unix_may_send(struct socket *sock, struct socket *other) | 969 | int security_unix_may_send(struct socket *sock, struct socket *other) |
976 | { | 970 | { |
977 | return security_ops->unix_may_send(sock, other); | 971 | return security_ops->unix_may_send(sock, other); |
978 | } | 972 | } |
979 | EXPORT_SYMBOL(security_unix_may_send); | 973 | EXPORT_SYMBOL(security_unix_may_send); |
980 | 974 | ||
981 | int security_socket_create(int family, int type, int protocol, int kern) | 975 | int security_socket_create(int family, int type, int protocol, int kern) |
982 | { | 976 | { |
983 | return security_ops->socket_create(family, type, protocol, kern); | 977 | return security_ops->socket_create(family, type, protocol, kern); |
984 | } | 978 | } |
985 | 979 | ||
986 | int security_socket_post_create(struct socket *sock, int family, | 980 | int security_socket_post_create(struct socket *sock, int family, |
987 | int type, int protocol, int kern) | 981 | int type, int protocol, int kern) |
988 | { | 982 | { |
989 | return security_ops->socket_post_create(sock, family, type, | 983 | return security_ops->socket_post_create(sock, family, type, |
990 | protocol, kern); | 984 | protocol, kern); |
991 | } | 985 | } |
992 | 986 | ||
993 | int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 987 | int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
994 | { | 988 | { |
995 | return security_ops->socket_bind(sock, address, addrlen); | 989 | return security_ops->socket_bind(sock, address, addrlen); |
996 | } | 990 | } |
997 | 991 | ||
998 | int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 992 | int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
999 | { | 993 | { |
1000 | return security_ops->socket_connect(sock, address, addrlen); | 994 | return security_ops->socket_connect(sock, address, addrlen); |
1001 | } | 995 | } |
1002 | 996 | ||
1003 | int security_socket_listen(struct socket *sock, int backlog) | 997 | int security_socket_listen(struct socket *sock, int backlog) |
1004 | { | 998 | { |
1005 | return security_ops->socket_listen(sock, backlog); | 999 | return security_ops->socket_listen(sock, backlog); |
1006 | } | 1000 | } |
1007 | 1001 | ||
1008 | int security_socket_accept(struct socket *sock, struct socket *newsock) | 1002 | int security_socket_accept(struct socket *sock, struct socket *newsock) |
1009 | { | 1003 | { |
1010 | return security_ops->socket_accept(sock, newsock); | 1004 | return security_ops->socket_accept(sock, newsock); |
1011 | } | 1005 | } |
1012 | 1006 | ||
1013 | int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) | 1007 | int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) |
1014 | { | 1008 | { |
1015 | return security_ops->socket_sendmsg(sock, msg, size); | 1009 | return security_ops->socket_sendmsg(sock, msg, size); |
1016 | } | 1010 | } |
1017 | 1011 | ||
1018 | int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 1012 | int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
1019 | int size, int flags) | 1013 | int size, int flags) |
1020 | { | 1014 | { |
1021 | return security_ops->socket_recvmsg(sock, msg, size, flags); | 1015 | return security_ops->socket_recvmsg(sock, msg, size, flags); |
1022 | } | 1016 | } |
1023 | 1017 | ||
1024 | int security_socket_getsockname(struct socket *sock) | 1018 | int security_socket_getsockname(struct socket *sock) |
1025 | { | 1019 | { |
1026 | return security_ops->socket_getsockname(sock); | 1020 | return security_ops->socket_getsockname(sock); |
1027 | } | 1021 | } |
1028 | 1022 | ||
1029 | int security_socket_getpeername(struct socket *sock) | 1023 | int security_socket_getpeername(struct socket *sock) |
1030 | { | 1024 | { |
1031 | return security_ops->socket_getpeername(sock); | 1025 | return security_ops->socket_getpeername(sock); |
1032 | } | 1026 | } |
1033 | 1027 | ||
1034 | int security_socket_getsockopt(struct socket *sock, int level, int optname) | 1028 | int security_socket_getsockopt(struct socket *sock, int level, int optname) |
1035 | { | 1029 | { |
1036 | return security_ops->socket_getsockopt(sock, level, optname); | 1030 | return security_ops->socket_getsockopt(sock, level, optname); |
1037 | } | 1031 | } |
1038 | 1032 | ||
1039 | int security_socket_setsockopt(struct socket *sock, int level, int optname) | 1033 | int security_socket_setsockopt(struct socket *sock, int level, int optname) |
1040 | { | 1034 | { |
1041 | return security_ops->socket_setsockopt(sock, level, optname); | 1035 | return security_ops->socket_setsockopt(sock, level, optname); |
1042 | } | 1036 | } |
1043 | 1037 | ||
1044 | int security_socket_shutdown(struct socket *sock, int how) | 1038 | int security_socket_shutdown(struct socket *sock, int how) |
1045 | { | 1039 | { |
1046 | return security_ops->socket_shutdown(sock, how); | 1040 | return security_ops->socket_shutdown(sock, how); |
1047 | } | 1041 | } |
1048 | 1042 | ||
1049 | int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1043 | int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
1050 | { | 1044 | { |
1051 | return security_ops->socket_sock_rcv_skb(sk, skb); | 1045 | return security_ops->socket_sock_rcv_skb(sk, skb); |
1052 | } | 1046 | } |
1053 | EXPORT_SYMBOL(security_sock_rcv_skb); | 1047 | EXPORT_SYMBOL(security_sock_rcv_skb); |
1054 | 1048 | ||
1055 | int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, | 1049 | int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
1056 | int __user *optlen, unsigned len) | 1050 | int __user *optlen, unsigned len) |
1057 | { | 1051 | { |
1058 | return security_ops->socket_getpeersec_stream(sock, optval, optlen, len); | 1052 | return security_ops->socket_getpeersec_stream(sock, optval, optlen, len); |
1059 | } | 1053 | } |
1060 | 1054 | ||
1061 | int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) | 1055 | int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) |
1062 | { | 1056 | { |
1063 | return security_ops->socket_getpeersec_dgram(sock, skb, secid); | 1057 | return security_ops->socket_getpeersec_dgram(sock, skb, secid); |
1064 | } | 1058 | } |
1065 | EXPORT_SYMBOL(security_socket_getpeersec_dgram); | 1059 | EXPORT_SYMBOL(security_socket_getpeersec_dgram); |
1066 | 1060 | ||
1067 | int security_sk_alloc(struct sock *sk, int family, gfp_t priority) | 1061 | int security_sk_alloc(struct sock *sk, int family, gfp_t priority) |
1068 | { | 1062 | { |
1069 | return security_ops->sk_alloc_security(sk, family, priority); | 1063 | return security_ops->sk_alloc_security(sk, family, priority); |
1070 | } | 1064 | } |
1071 | 1065 | ||
1072 | void security_sk_free(struct sock *sk) | 1066 | void security_sk_free(struct sock *sk) |
1073 | { | 1067 | { |
1074 | security_ops->sk_free_security(sk); | 1068 | security_ops->sk_free_security(sk); |
1075 | } | 1069 | } |
1076 | 1070 | ||
1077 | void security_sk_clone(const struct sock *sk, struct sock *newsk) | 1071 | void security_sk_clone(const struct sock *sk, struct sock *newsk) |
1078 | { | 1072 | { |
1079 | security_ops->sk_clone_security(sk, newsk); | 1073 | security_ops->sk_clone_security(sk, newsk); |
1080 | } | 1074 | } |
1081 | EXPORT_SYMBOL(security_sk_clone); | 1075 | EXPORT_SYMBOL(security_sk_clone); |
1082 | 1076 | ||
1083 | void security_sk_classify_flow(struct sock *sk, struct flowi *fl) | 1077 | void security_sk_classify_flow(struct sock *sk, struct flowi *fl) |
1084 | { | 1078 | { |
1085 | security_ops->sk_getsecid(sk, &fl->flowi_secid); | 1079 | security_ops->sk_getsecid(sk, &fl->flowi_secid); |
1086 | } | 1080 | } |
1087 | EXPORT_SYMBOL(security_sk_classify_flow); | 1081 | EXPORT_SYMBOL(security_sk_classify_flow); |
1088 | 1082 | ||
1089 | void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) | 1083 | void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) |
1090 | { | 1084 | { |
1091 | security_ops->req_classify_flow(req, fl); | 1085 | security_ops->req_classify_flow(req, fl); |
1092 | } | 1086 | } |
1093 | EXPORT_SYMBOL(security_req_classify_flow); | 1087 | EXPORT_SYMBOL(security_req_classify_flow); |
1094 | 1088 | ||
1095 | void security_sock_graft(struct sock *sk, struct socket *parent) | 1089 | void security_sock_graft(struct sock *sk, struct socket *parent) |
1096 | { | 1090 | { |
1097 | security_ops->sock_graft(sk, parent); | 1091 | security_ops->sock_graft(sk, parent); |
1098 | } | 1092 | } |
1099 | EXPORT_SYMBOL(security_sock_graft); | 1093 | EXPORT_SYMBOL(security_sock_graft); |
1100 | 1094 | ||
1101 | int security_inet_conn_request(struct sock *sk, | 1095 | int security_inet_conn_request(struct sock *sk, |
1102 | struct sk_buff *skb, struct request_sock *req) | 1096 | struct sk_buff *skb, struct request_sock *req) |
1103 | { | 1097 | { |
1104 | return security_ops->inet_conn_request(sk, skb, req); | 1098 | return security_ops->inet_conn_request(sk, skb, req); |
1105 | } | 1099 | } |
1106 | EXPORT_SYMBOL(security_inet_conn_request); | 1100 | EXPORT_SYMBOL(security_inet_conn_request); |
1107 | 1101 | ||
1108 | void security_inet_csk_clone(struct sock *newsk, | 1102 | void security_inet_csk_clone(struct sock *newsk, |
1109 | const struct request_sock *req) | 1103 | const struct request_sock *req) |
1110 | { | 1104 | { |
1111 | security_ops->inet_csk_clone(newsk, req); | 1105 | security_ops->inet_csk_clone(newsk, req); |
1112 | } | 1106 | } |
1113 | 1107 | ||
1114 | void security_inet_conn_established(struct sock *sk, | 1108 | void security_inet_conn_established(struct sock *sk, |
1115 | struct sk_buff *skb) | 1109 | struct sk_buff *skb) |
1116 | { | 1110 | { |
1117 | security_ops->inet_conn_established(sk, skb); | 1111 | security_ops->inet_conn_established(sk, skb); |
1118 | } | 1112 | } |
1119 | 1113 | ||
1120 | int security_secmark_relabel_packet(u32 secid) | 1114 | int security_secmark_relabel_packet(u32 secid) |
1121 | { | 1115 | { |
1122 | return security_ops->secmark_relabel_packet(secid); | 1116 | return security_ops->secmark_relabel_packet(secid); |
1123 | } | 1117 | } |
1124 | EXPORT_SYMBOL(security_secmark_relabel_packet); | 1118 | EXPORT_SYMBOL(security_secmark_relabel_packet); |
1125 | 1119 | ||
1126 | void security_secmark_refcount_inc(void) | 1120 | void security_secmark_refcount_inc(void) |
1127 | { | 1121 | { |
1128 | security_ops->secmark_refcount_inc(); | 1122 | security_ops->secmark_refcount_inc(); |
1129 | } | 1123 | } |
1130 | EXPORT_SYMBOL(security_secmark_refcount_inc); | 1124 | EXPORT_SYMBOL(security_secmark_refcount_inc); |
1131 | 1125 | ||
1132 | void security_secmark_refcount_dec(void) | 1126 | void security_secmark_refcount_dec(void) |
1133 | { | 1127 | { |
1134 | security_ops->secmark_refcount_dec(); | 1128 | security_ops->secmark_refcount_dec(); |
1135 | } | 1129 | } |
1136 | EXPORT_SYMBOL(security_secmark_refcount_dec); | 1130 | EXPORT_SYMBOL(security_secmark_refcount_dec); |
1137 | 1131 | ||
1138 | int security_tun_dev_create(void) | 1132 | int security_tun_dev_create(void) |
1139 | { | 1133 | { |
1140 | return security_ops->tun_dev_create(); | 1134 | return security_ops->tun_dev_create(); |
1141 | } | 1135 | } |
1142 | EXPORT_SYMBOL(security_tun_dev_create); | 1136 | EXPORT_SYMBOL(security_tun_dev_create); |
1143 | 1137 | ||
1144 | void security_tun_dev_post_create(struct sock *sk) | 1138 | void security_tun_dev_post_create(struct sock *sk) |
1145 | { | 1139 | { |
1146 | return security_ops->tun_dev_post_create(sk); | 1140 | return security_ops->tun_dev_post_create(sk); |
1147 | } | 1141 | } |
1148 | EXPORT_SYMBOL(security_tun_dev_post_create); | 1142 | EXPORT_SYMBOL(security_tun_dev_post_create); |
1149 | 1143 | ||
1150 | int security_tun_dev_attach(struct sock *sk) | 1144 | int security_tun_dev_attach(struct sock *sk) |
1151 | { | 1145 | { |
1152 | return security_ops->tun_dev_attach(sk); | 1146 | return security_ops->tun_dev_attach(sk); |
1153 | } | 1147 | } |
1154 | EXPORT_SYMBOL(security_tun_dev_attach); | 1148 | EXPORT_SYMBOL(security_tun_dev_attach); |
1155 | 1149 | ||
1156 | #endif /* CONFIG_SECURITY_NETWORK */ | 1150 | #endif /* CONFIG_SECURITY_NETWORK */ |
1157 | 1151 | ||
1158 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1152 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1159 | 1153 | ||
1160 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) | 1154 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) |
1161 | { | 1155 | { |
1162 | return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx); | 1156 | return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx); |
1163 | } | 1157 | } |
1164 | EXPORT_SYMBOL(security_xfrm_policy_alloc); | 1158 | EXPORT_SYMBOL(security_xfrm_policy_alloc); |
1165 | 1159 | ||
1166 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, | 1160 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, |
1167 | struct xfrm_sec_ctx **new_ctxp) | 1161 | struct xfrm_sec_ctx **new_ctxp) |
1168 | { | 1162 | { |
1169 | return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp); | 1163 | return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp); |
1170 | } | 1164 | } |
1171 | 1165 | ||
1172 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx) | 1166 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx) |
1173 | { | 1167 | { |
1174 | security_ops->xfrm_policy_free_security(ctx); | 1168 | security_ops->xfrm_policy_free_security(ctx); |
1175 | } | 1169 | } |
1176 | EXPORT_SYMBOL(security_xfrm_policy_free); | 1170 | EXPORT_SYMBOL(security_xfrm_policy_free); |
1177 | 1171 | ||
1178 | int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) | 1172 | int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) |
1179 | { | 1173 | { |
1180 | return security_ops->xfrm_policy_delete_security(ctx); | 1174 | return security_ops->xfrm_policy_delete_security(ctx); |
1181 | } | 1175 | } |
1182 | 1176 | ||
1183 | int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) | 1177 | int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) |
1184 | { | 1178 | { |
1185 | return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0); | 1179 | return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0); |
1186 | } | 1180 | } |
1187 | EXPORT_SYMBOL(security_xfrm_state_alloc); | 1181 | EXPORT_SYMBOL(security_xfrm_state_alloc); |
1188 | 1182 | ||
1189 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | 1183 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, |
1190 | struct xfrm_sec_ctx *polsec, u32 secid) | 1184 | struct xfrm_sec_ctx *polsec, u32 secid) |
1191 | { | 1185 | { |
1192 | if (!polsec) | 1186 | if (!polsec) |
1193 | return 0; | 1187 | return 0; |
1194 | /* | 1188 | /* |
1195 | * We want the context to be taken from secid which is usually | 1189 | * We want the context to be taken from secid which is usually |
1196 | * from the sock. | 1190 | * from the sock. |
1197 | */ | 1191 | */ |
1198 | return security_ops->xfrm_state_alloc_security(x, NULL, secid); | 1192 | return security_ops->xfrm_state_alloc_security(x, NULL, secid); |
1199 | } | 1193 | } |
1200 | 1194 | ||
1201 | int security_xfrm_state_delete(struct xfrm_state *x) | 1195 | int security_xfrm_state_delete(struct xfrm_state *x) |
1202 | { | 1196 | { |
1203 | return security_ops->xfrm_state_delete_security(x); | 1197 | return security_ops->xfrm_state_delete_security(x); |
1204 | } | 1198 | } |
1205 | EXPORT_SYMBOL(security_xfrm_state_delete); | 1199 | EXPORT_SYMBOL(security_xfrm_state_delete); |
1206 | 1200 | ||
1207 | void security_xfrm_state_free(struct xfrm_state *x) | 1201 | void security_xfrm_state_free(struct xfrm_state *x) |
1208 | { | 1202 | { |
1209 | security_ops->xfrm_state_free_security(x); | 1203 | security_ops->xfrm_state_free_security(x); |
1210 | } | 1204 | } |
1211 | 1205 | ||
1212 | int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) | 1206 | int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) |
1213 | { | 1207 | { |
1214 | return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir); | 1208 | return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir); |
1215 | } | 1209 | } |
1216 | 1210 | ||
1217 | int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | 1211 | int security_xfrm_state_pol_flow_match(struct xfrm_state *x, |
1218 | struct xfrm_policy *xp, | 1212 | struct xfrm_policy *xp, |
1219 | const struct flowi *fl) | 1213 | const struct flowi *fl) |
1220 | { | 1214 | { |
1221 | return security_ops->xfrm_state_pol_flow_match(x, xp, fl); | 1215 | return security_ops->xfrm_state_pol_flow_match(x, xp, fl); |
1222 | } | 1216 | } |
1223 | 1217 | ||
1224 | int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) | 1218 | int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) |
1225 | { | 1219 | { |
1226 | return security_ops->xfrm_decode_session(skb, secid, 1); | 1220 | return security_ops->xfrm_decode_session(skb, secid, 1); |
1227 | } | 1221 | } |
1228 | 1222 | ||
1229 | void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) | 1223 | void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) |
1230 | { | 1224 | { |
1231 | int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0); | 1225 | int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0); |
1232 | 1226 | ||
1233 | BUG_ON(rc); | 1227 | BUG_ON(rc); |
1234 | } | 1228 | } |
1235 | EXPORT_SYMBOL(security_skb_classify_flow); | 1229 | EXPORT_SYMBOL(security_skb_classify_flow); |
1236 | 1230 | ||
1237 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 1231 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
1238 | 1232 | ||
1239 | #ifdef CONFIG_KEYS | 1233 | #ifdef CONFIG_KEYS |
1240 | 1234 | ||
1241 | int security_key_alloc(struct key *key, const struct cred *cred, | 1235 | int security_key_alloc(struct key *key, const struct cred *cred, |
1242 | unsigned long flags) | 1236 | unsigned long flags) |
1243 | { | 1237 | { |
1244 | return security_ops->key_alloc(key, cred, flags); | 1238 | return security_ops->key_alloc(key, cred, flags); |
1245 | } | 1239 | } |
1246 | 1240 | ||
1247 | void security_key_free(struct key *key) | 1241 | void security_key_free(struct key *key) |
1248 | { | 1242 | { |
1249 | security_ops->key_free(key); | 1243 | security_ops->key_free(key); |
1250 | } | 1244 | } |
1251 | 1245 | ||
1252 | int security_key_permission(key_ref_t key_ref, | 1246 | int security_key_permission(key_ref_t key_ref, |
1253 | const struct cred *cred, key_perm_t perm) | 1247 | const struct cred *cred, key_perm_t perm) |
1254 | { | 1248 | { |
1255 | return security_ops->key_permission(key_ref, cred, perm); | 1249 | return security_ops->key_permission(key_ref, cred, perm); |
1256 | } | 1250 | } |
1257 | 1251 | ||
1258 | int security_key_getsecurity(struct key *key, char **_buffer) | 1252 | int security_key_getsecurity(struct key *key, char **_buffer) |
1259 | { | 1253 | { |
1260 | return security_ops->key_getsecurity(key, _buffer); | 1254 | return security_ops->key_getsecurity(key, _buffer); |
1261 | } | 1255 | } |
1262 | 1256 | ||
1263 | #endif /* CONFIG_KEYS */ | 1257 | #endif /* CONFIG_KEYS */ |
1264 | 1258 | ||
1265 | #ifdef CONFIG_AUDIT | 1259 | #ifdef CONFIG_AUDIT |
1266 | 1260 | ||
1267 | int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) | 1261 | int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) |
1268 | { | 1262 | { |
1269 | return security_ops->audit_rule_init(field, op, rulestr, lsmrule); | 1263 | return security_ops->audit_rule_init(field, op, rulestr, lsmrule); |
1270 | } | 1264 | } |
1271 | 1265 | ||
1272 | int security_audit_rule_known(struct audit_krule *krule) | 1266 | int security_audit_rule_known(struct audit_krule *krule) |
1273 | { | 1267 | { |
1274 | return security_ops->audit_rule_known(krule); | 1268 | return security_ops->audit_rule_known(krule); |
1275 | } | 1269 | } |
1276 | 1270 | ||
1277 | void security_audit_rule_free(void *lsmrule) | 1271 | void security_audit_rule_free(void *lsmrule) |
1278 | { | 1272 | { |
1279 | security_ops->audit_rule_free(lsmrule); | 1273 | security_ops->audit_rule_free(lsmrule); |
1280 | } | 1274 | } |
1281 | 1275 | ||
1282 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, | 1276 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, |
1283 | struct audit_context *actx) | 1277 | struct audit_context *actx) |
1284 | { | 1278 | { |
1285 | return security_ops->audit_rule_match(secid, field, op, lsmrule, actx); | 1279 | return security_ops->audit_rule_match(secid, field, op, lsmrule, actx); |
1286 | } | 1280 | } |
1287 | 1281 | ||
1288 | #endif /* CONFIG_AUDIT */ | 1282 | #endif /* CONFIG_AUDIT */ |
1289 | 1283 |
security/selinux/hooks.c
1 | /* | 1 | /* |
2 | * NSA Security-Enhanced Linux (SELinux) security module | 2 | * NSA Security-Enhanced Linux (SELinux) security module |
3 | * | 3 | * |
4 | * This file contains the SELinux hook function implementations. | 4 | * This file contains the SELinux hook function implementations. |
5 | * | 5 | * |
6 | * Authors: Stephen Smalley, <sds@epoch.ncsc.mil> | 6 | * Authors: Stephen Smalley, <sds@epoch.ncsc.mil> |
7 | * Chris Vance, <cvance@nai.com> | 7 | * Chris Vance, <cvance@nai.com> |
8 | * Wayne Salamon, <wsalamon@nai.com> | 8 | * Wayne Salamon, <wsalamon@nai.com> |
9 | * James Morris <jmorris@redhat.com> | 9 | * James Morris <jmorris@redhat.com> |
10 | * | 10 | * |
11 | * Copyright (C) 2001,2002 Networks Associates Technology, Inc. | 11 | * Copyright (C) 2001,2002 Networks Associates Technology, Inc. |
12 | * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com> | 12 | * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com> |
13 | * Eric Paris <eparis@redhat.com> | 13 | * Eric Paris <eparis@redhat.com> |
14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
15 | * <dgoeddel@trustedcs.com> | 15 | * <dgoeddel@trustedcs.com> |
16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. | 16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. |
17 | * Paul Moore <paul@paul-moore.com> | 17 | * Paul Moore <paul@paul-moore.com> |
18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. |
19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> |
20 | * | 20 | * |
21 | * This program is free software; you can redistribute it and/or modify | 21 | * This program is free software; you can redistribute it and/or modify |
22 | * it under the terms of the GNU General Public License version 2, | 22 | * it under the terms of the GNU General Public License version 2, |
23 | * as published by the Free Software Foundation. | 23 | * as published by the Free Software Foundation. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kd.h> | 27 | #include <linux/kd.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/tracehook.h> | 29 | #include <linux/tracehook.h> |
30 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
31 | #include <linux/ext2_fs.h> | 31 | #include <linux/ext2_fs.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/security.h> | 33 | #include <linux/security.h> |
34 | #include <linux/xattr.h> | 34 | #include <linux/xattr.h> |
35 | #include <linux/capability.h> | 35 | #include <linux/capability.h> |
36 | #include <linux/unistd.h> | 36 | #include <linux/unistd.h> |
37 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
38 | #include <linux/mman.h> | 38 | #include <linux/mman.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
41 | #include <linux/proc_fs.h> | 41 | #include <linux/proc_fs.h> |
42 | #include <linux/swap.h> | 42 | #include <linux/swap.h> |
43 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
44 | #include <linux/syscalls.h> | 44 | #include <linux/syscalls.h> |
45 | #include <linux/dcache.h> | 45 | #include <linux/dcache.h> |
46 | #include <linux/file.h> | 46 | #include <linux/file.h> |
47 | #include <linux/fdtable.h> | 47 | #include <linux/fdtable.h> |
48 | #include <linux/namei.h> | 48 | #include <linux/namei.h> |
49 | #include <linux/mount.h> | 49 | #include <linux/mount.h> |
50 | #include <linux/netfilter_ipv4.h> | 50 | #include <linux/netfilter_ipv4.h> |
51 | #include <linux/netfilter_ipv6.h> | 51 | #include <linux/netfilter_ipv6.h> |
52 | #include <linux/tty.h> | 52 | #include <linux/tty.h> |
53 | #include <net/icmp.h> | 53 | #include <net/icmp.h> |
54 | #include <net/ip.h> /* for local_port_range[] */ | 54 | #include <net/ip.h> /* for local_port_range[] */ |
55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
56 | #include <net/net_namespace.h> | 56 | #include <net/net_namespace.h> |
57 | #include <net/netlabel.h> | 57 | #include <net/netlabel.h> |
58 | #include <linux/uaccess.h> | 58 | #include <linux/uaccess.h> |
59 | #include <asm/ioctls.h> | 59 | #include <asm/ioctls.h> |
60 | #include <linux/atomic.h> | 60 | #include <linux/atomic.h> |
61 | #include <linux/bitops.h> | 61 | #include <linux/bitops.h> |
62 | #include <linux/interrupt.h> | 62 | #include <linux/interrupt.h> |
63 | #include <linux/netdevice.h> /* for network interface checks */ | 63 | #include <linux/netdevice.h> /* for network interface checks */ |
64 | #include <linux/netlink.h> | 64 | #include <linux/netlink.h> |
65 | #include <linux/tcp.h> | 65 | #include <linux/tcp.h> |
66 | #include <linux/udp.h> | 66 | #include <linux/udp.h> |
67 | #include <linux/dccp.h> | 67 | #include <linux/dccp.h> |
68 | #include <linux/quota.h> | 68 | #include <linux/quota.h> |
69 | #include <linux/un.h> /* for Unix socket types */ | 69 | #include <linux/un.h> /* for Unix socket types */ |
70 | #include <net/af_unix.h> /* for Unix socket types */ | 70 | #include <net/af_unix.h> /* for Unix socket types */ |
71 | #include <linux/parser.h> | 71 | #include <linux/parser.h> |
72 | #include <linux/nfs_mount.h> | 72 | #include <linux/nfs_mount.h> |
73 | #include <net/ipv6.h> | 73 | #include <net/ipv6.h> |
74 | #include <linux/hugetlb.h> | 74 | #include <linux/hugetlb.h> |
75 | #include <linux/personality.h> | 75 | #include <linux/personality.h> |
76 | #include <linux/audit.h> | 76 | #include <linux/audit.h> |
77 | #include <linux/string.h> | 77 | #include <linux/string.h> |
78 | #include <linux/selinux.h> | 78 | #include <linux/selinux.h> |
79 | #include <linux/mutex.h> | 79 | #include <linux/mutex.h> |
80 | #include <linux/posix-timers.h> | 80 | #include <linux/posix-timers.h> |
81 | #include <linux/syslog.h> | 81 | #include <linux/syslog.h> |
82 | #include <linux/user_namespace.h> | 82 | #include <linux/user_namespace.h> |
83 | 83 | ||
84 | #include "avc.h" | 84 | #include "avc.h" |
85 | #include "objsec.h" | 85 | #include "objsec.h" |
86 | #include "netif.h" | 86 | #include "netif.h" |
87 | #include "netnode.h" | 87 | #include "netnode.h" |
88 | #include "netport.h" | 88 | #include "netport.h" |
89 | #include "xfrm.h" | 89 | #include "xfrm.h" |
90 | #include "netlabel.h" | 90 | #include "netlabel.h" |
91 | #include "audit.h" | 91 | #include "audit.h" |
92 | #include "avc_ss.h" | 92 | #include "avc_ss.h" |
93 | 93 | ||
94 | #define NUM_SEL_MNT_OPTS 5 | 94 | #define NUM_SEL_MNT_OPTS 5 |
95 | 95 | ||
96 | extern struct security_operations *security_ops; | 96 | extern struct security_operations *security_ops; |
97 | 97 | ||
98 | /* SECMARK reference count */ | 98 | /* SECMARK reference count */ |
99 | static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); | 99 | static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); |
100 | 100 | ||
101 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | 101 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP |
102 | int selinux_enforcing; | 102 | int selinux_enforcing; |
103 | 103 | ||
104 | static int __init enforcing_setup(char *str) | 104 | static int __init enforcing_setup(char *str) |
105 | { | 105 | { |
106 | unsigned long enforcing; | 106 | unsigned long enforcing; |
107 | if (!strict_strtoul(str, 0, &enforcing)) | 107 | if (!strict_strtoul(str, 0, &enforcing)) |
108 | selinux_enforcing = enforcing ? 1 : 0; | 108 | selinux_enforcing = enforcing ? 1 : 0; |
109 | return 1; | 109 | return 1; |
110 | } | 110 | } |
111 | __setup("enforcing=", enforcing_setup); | 111 | __setup("enforcing=", enforcing_setup); |
112 | #endif | 112 | #endif |
113 | 113 | ||
114 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | 114 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM |
115 | int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; | 115 | int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; |
116 | 116 | ||
117 | static int __init selinux_enabled_setup(char *str) | 117 | static int __init selinux_enabled_setup(char *str) |
118 | { | 118 | { |
119 | unsigned long enabled; | 119 | unsigned long enabled; |
120 | if (!strict_strtoul(str, 0, &enabled)) | 120 | if (!strict_strtoul(str, 0, &enabled)) |
121 | selinux_enabled = enabled ? 1 : 0; | 121 | selinux_enabled = enabled ? 1 : 0; |
122 | return 1; | 122 | return 1; |
123 | } | 123 | } |
124 | __setup("selinux=", selinux_enabled_setup); | 124 | __setup("selinux=", selinux_enabled_setup); |
125 | #else | 125 | #else |
126 | int selinux_enabled = 1; | 126 | int selinux_enabled = 1; |
127 | #endif | 127 | #endif |
128 | 128 | ||
129 | static struct kmem_cache *sel_inode_cache; | 129 | static struct kmem_cache *sel_inode_cache; |
130 | 130 | ||
131 | /** | 131 | /** |
132 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled | 132 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled |
133 | * | 133 | * |
134 | * Description: | 134 | * Description: |
135 | * This function checks the SECMARK reference counter to see if any SECMARK | 135 | * This function checks the SECMARK reference counter to see if any SECMARK |
136 | * targets are currently configured, if the reference counter is greater than | 136 | * targets are currently configured, if the reference counter is greater than |
137 | * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is | 137 | * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is |
138 | * enabled, false (0) if SECMARK is disabled. | 138 | * enabled, false (0) if SECMARK is disabled. |
139 | * | 139 | * |
140 | */ | 140 | */ |
141 | static int selinux_secmark_enabled(void) | 141 | static int selinux_secmark_enabled(void) |
142 | { | 142 | { |
143 | return (atomic_read(&selinux_secmark_refcount) > 0); | 143 | return (atomic_read(&selinux_secmark_refcount) > 0); |
144 | } | 144 | } |
145 | 145 | ||
146 | /* | 146 | /* |
147 | * initialise the security for the init task | 147 | * initialise the security for the init task |
148 | */ | 148 | */ |
149 | static void cred_init_security(void) | 149 | static void cred_init_security(void) |
150 | { | 150 | { |
151 | struct cred *cred = (struct cred *) current->real_cred; | 151 | struct cred *cred = (struct cred *) current->real_cred; |
152 | struct task_security_struct *tsec; | 152 | struct task_security_struct *tsec; |
153 | 153 | ||
154 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); | 154 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); |
155 | if (!tsec) | 155 | if (!tsec) |
156 | panic("SELinux: Failed to initialize initial task.\n"); | 156 | panic("SELinux: Failed to initialize initial task.\n"); |
157 | 157 | ||
158 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | 158 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
159 | cred->security = tsec; | 159 | cred->security = tsec; |
160 | } | 160 | } |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * get the security ID of a set of credentials | 163 | * get the security ID of a set of credentials |
164 | */ | 164 | */ |
165 | static inline u32 cred_sid(const struct cred *cred) | 165 | static inline u32 cred_sid(const struct cred *cred) |
166 | { | 166 | { |
167 | const struct task_security_struct *tsec; | 167 | const struct task_security_struct *tsec; |
168 | 168 | ||
169 | tsec = cred->security; | 169 | tsec = cred->security; |
170 | return tsec->sid; | 170 | return tsec->sid; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * get the objective security ID of a task | 174 | * get the objective security ID of a task |
175 | */ | 175 | */ |
176 | static inline u32 task_sid(const struct task_struct *task) | 176 | static inline u32 task_sid(const struct task_struct *task) |
177 | { | 177 | { |
178 | u32 sid; | 178 | u32 sid; |
179 | 179 | ||
180 | rcu_read_lock(); | 180 | rcu_read_lock(); |
181 | sid = cred_sid(__task_cred(task)); | 181 | sid = cred_sid(__task_cred(task)); |
182 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
183 | return sid; | 183 | return sid; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * get the subjective security ID of the current task | 187 | * get the subjective security ID of the current task |
188 | */ | 188 | */ |
189 | static inline u32 current_sid(void) | 189 | static inline u32 current_sid(void) |
190 | { | 190 | { |
191 | const struct task_security_struct *tsec = current_security(); | 191 | const struct task_security_struct *tsec = current_security(); |
192 | 192 | ||
193 | return tsec->sid; | 193 | return tsec->sid; |
194 | } | 194 | } |
195 | 195 | ||
196 | /* Allocate and free functions for each kind of security blob. */ | 196 | /* Allocate and free functions for each kind of security blob. */ |
197 | 197 | ||
198 | static int inode_alloc_security(struct inode *inode) | 198 | static int inode_alloc_security(struct inode *inode) |
199 | { | 199 | { |
200 | struct inode_security_struct *isec; | 200 | struct inode_security_struct *isec; |
201 | u32 sid = current_sid(); | 201 | u32 sid = current_sid(); |
202 | 202 | ||
203 | isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS); | 203 | isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS); |
204 | if (!isec) | 204 | if (!isec) |
205 | return -ENOMEM; | 205 | return -ENOMEM; |
206 | 206 | ||
207 | mutex_init(&isec->lock); | 207 | mutex_init(&isec->lock); |
208 | INIT_LIST_HEAD(&isec->list); | 208 | INIT_LIST_HEAD(&isec->list); |
209 | isec->inode = inode; | 209 | isec->inode = inode; |
210 | isec->sid = SECINITSID_UNLABELED; | 210 | isec->sid = SECINITSID_UNLABELED; |
211 | isec->sclass = SECCLASS_FILE; | 211 | isec->sclass = SECCLASS_FILE; |
212 | isec->task_sid = sid; | 212 | isec->task_sid = sid; |
213 | inode->i_security = isec; | 213 | inode->i_security = isec; |
214 | 214 | ||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void inode_free_security(struct inode *inode) | 218 | static void inode_free_security(struct inode *inode) |
219 | { | 219 | { |
220 | struct inode_security_struct *isec = inode->i_security; | 220 | struct inode_security_struct *isec = inode->i_security; |
221 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; | 221 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; |
222 | 222 | ||
223 | spin_lock(&sbsec->isec_lock); | 223 | spin_lock(&sbsec->isec_lock); |
224 | if (!list_empty(&isec->list)) | 224 | if (!list_empty(&isec->list)) |
225 | list_del_init(&isec->list); | 225 | list_del_init(&isec->list); |
226 | spin_unlock(&sbsec->isec_lock); | 226 | spin_unlock(&sbsec->isec_lock); |
227 | 227 | ||
228 | inode->i_security = NULL; | 228 | inode->i_security = NULL; |
229 | kmem_cache_free(sel_inode_cache, isec); | 229 | kmem_cache_free(sel_inode_cache, isec); |
230 | } | 230 | } |
231 | 231 | ||
232 | static int file_alloc_security(struct file *file) | 232 | static int file_alloc_security(struct file *file) |
233 | { | 233 | { |
234 | struct file_security_struct *fsec; | 234 | struct file_security_struct *fsec; |
235 | u32 sid = current_sid(); | 235 | u32 sid = current_sid(); |
236 | 236 | ||
237 | fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL); | 237 | fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL); |
238 | if (!fsec) | 238 | if (!fsec) |
239 | return -ENOMEM; | 239 | return -ENOMEM; |
240 | 240 | ||
241 | fsec->sid = sid; | 241 | fsec->sid = sid; |
242 | fsec->fown_sid = sid; | 242 | fsec->fown_sid = sid; |
243 | file->f_security = fsec; | 243 | file->f_security = fsec; |
244 | 244 | ||
245 | return 0; | 245 | return 0; |
246 | } | 246 | } |
247 | 247 | ||
248 | static void file_free_security(struct file *file) | 248 | static void file_free_security(struct file *file) |
249 | { | 249 | { |
250 | struct file_security_struct *fsec = file->f_security; | 250 | struct file_security_struct *fsec = file->f_security; |
251 | file->f_security = NULL; | 251 | file->f_security = NULL; |
252 | kfree(fsec); | 252 | kfree(fsec); |
253 | } | 253 | } |
254 | 254 | ||
255 | static int superblock_alloc_security(struct super_block *sb) | 255 | static int superblock_alloc_security(struct super_block *sb) |
256 | { | 256 | { |
257 | struct superblock_security_struct *sbsec; | 257 | struct superblock_security_struct *sbsec; |
258 | 258 | ||
259 | sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL); | 259 | sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL); |
260 | if (!sbsec) | 260 | if (!sbsec) |
261 | return -ENOMEM; | 261 | return -ENOMEM; |
262 | 262 | ||
263 | mutex_init(&sbsec->lock); | 263 | mutex_init(&sbsec->lock); |
264 | INIT_LIST_HEAD(&sbsec->isec_head); | 264 | INIT_LIST_HEAD(&sbsec->isec_head); |
265 | spin_lock_init(&sbsec->isec_lock); | 265 | spin_lock_init(&sbsec->isec_lock); |
266 | sbsec->sb = sb; | 266 | sbsec->sb = sb; |
267 | sbsec->sid = SECINITSID_UNLABELED; | 267 | sbsec->sid = SECINITSID_UNLABELED; |
268 | sbsec->def_sid = SECINITSID_FILE; | 268 | sbsec->def_sid = SECINITSID_FILE; |
269 | sbsec->mntpoint_sid = SECINITSID_UNLABELED; | 269 | sbsec->mntpoint_sid = SECINITSID_UNLABELED; |
270 | sb->s_security = sbsec; | 270 | sb->s_security = sbsec; |
271 | 271 | ||
272 | return 0; | 272 | return 0; |
273 | } | 273 | } |
274 | 274 | ||
275 | static void superblock_free_security(struct super_block *sb) | 275 | static void superblock_free_security(struct super_block *sb) |
276 | { | 276 | { |
277 | struct superblock_security_struct *sbsec = sb->s_security; | 277 | struct superblock_security_struct *sbsec = sb->s_security; |
278 | sb->s_security = NULL; | 278 | sb->s_security = NULL; |
279 | kfree(sbsec); | 279 | kfree(sbsec); |
280 | } | 280 | } |
281 | 281 | ||
282 | /* The file system's label must be initialized prior to use. */ | 282 | /* The file system's label must be initialized prior to use. */ |
283 | 283 | ||
284 | static const char *labeling_behaviors[6] = { | 284 | static const char *labeling_behaviors[6] = { |
285 | "uses xattr", | 285 | "uses xattr", |
286 | "uses transition SIDs", | 286 | "uses transition SIDs", |
287 | "uses task SIDs", | 287 | "uses task SIDs", |
288 | "uses genfs_contexts", | 288 | "uses genfs_contexts", |
289 | "not configured for labeling", | 289 | "not configured for labeling", |
290 | "uses mountpoint labeling", | 290 | "uses mountpoint labeling", |
291 | }; | 291 | }; |
292 | 292 | ||
293 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); | 293 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); |
294 | 294 | ||
295 | static inline int inode_doinit(struct inode *inode) | 295 | static inline int inode_doinit(struct inode *inode) |
296 | { | 296 | { |
297 | return inode_doinit_with_dentry(inode, NULL); | 297 | return inode_doinit_with_dentry(inode, NULL); |
298 | } | 298 | } |
299 | 299 | ||
300 | enum { | 300 | enum { |
301 | Opt_error = -1, | 301 | Opt_error = -1, |
302 | Opt_context = 1, | 302 | Opt_context = 1, |
303 | Opt_fscontext = 2, | 303 | Opt_fscontext = 2, |
304 | Opt_defcontext = 3, | 304 | Opt_defcontext = 3, |
305 | Opt_rootcontext = 4, | 305 | Opt_rootcontext = 4, |
306 | Opt_labelsupport = 5, | 306 | Opt_labelsupport = 5, |
307 | }; | 307 | }; |
308 | 308 | ||
309 | static const match_table_t tokens = { | 309 | static const match_table_t tokens = { |
310 | {Opt_context, CONTEXT_STR "%s"}, | 310 | {Opt_context, CONTEXT_STR "%s"}, |
311 | {Opt_fscontext, FSCONTEXT_STR "%s"}, | 311 | {Opt_fscontext, FSCONTEXT_STR "%s"}, |
312 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, | 312 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, |
313 | {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, | 313 | {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, |
314 | {Opt_labelsupport, LABELSUPP_STR}, | 314 | {Opt_labelsupport, LABELSUPP_STR}, |
315 | {Opt_error, NULL}, | 315 | {Opt_error, NULL}, |
316 | }; | 316 | }; |
317 | 317 | ||
318 | #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" | 318 | #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" |
319 | 319 | ||
320 | static int may_context_mount_sb_relabel(u32 sid, | 320 | static int may_context_mount_sb_relabel(u32 sid, |
321 | struct superblock_security_struct *sbsec, | 321 | struct superblock_security_struct *sbsec, |
322 | const struct cred *cred) | 322 | const struct cred *cred) |
323 | { | 323 | { |
324 | const struct task_security_struct *tsec = cred->security; | 324 | const struct task_security_struct *tsec = cred->security; |
325 | int rc; | 325 | int rc; |
326 | 326 | ||
327 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 327 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, |
328 | FILESYSTEM__RELABELFROM, NULL); | 328 | FILESYSTEM__RELABELFROM, NULL); |
329 | if (rc) | 329 | if (rc) |
330 | return rc; | 330 | return rc; |
331 | 331 | ||
332 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, | 332 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, |
333 | FILESYSTEM__RELABELTO, NULL); | 333 | FILESYSTEM__RELABELTO, NULL); |
334 | return rc; | 334 | return rc; |
335 | } | 335 | } |
336 | 336 | ||
337 | static int may_context_mount_inode_relabel(u32 sid, | 337 | static int may_context_mount_inode_relabel(u32 sid, |
338 | struct superblock_security_struct *sbsec, | 338 | struct superblock_security_struct *sbsec, |
339 | const struct cred *cred) | 339 | const struct cred *cred) |
340 | { | 340 | { |
341 | const struct task_security_struct *tsec = cred->security; | 341 | const struct task_security_struct *tsec = cred->security; |
342 | int rc; | 342 | int rc; |
343 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 343 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, |
344 | FILESYSTEM__RELABELFROM, NULL); | 344 | FILESYSTEM__RELABELFROM, NULL); |
345 | if (rc) | 345 | if (rc) |
346 | return rc; | 346 | return rc; |
347 | 347 | ||
348 | rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, | 348 | rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, |
349 | FILESYSTEM__ASSOCIATE, NULL); | 349 | FILESYSTEM__ASSOCIATE, NULL); |
350 | return rc; | 350 | return rc; |
351 | } | 351 | } |
352 | 352 | ||
353 | static int sb_finish_set_opts(struct super_block *sb) | 353 | static int sb_finish_set_opts(struct super_block *sb) |
354 | { | 354 | { |
355 | struct superblock_security_struct *sbsec = sb->s_security; | 355 | struct superblock_security_struct *sbsec = sb->s_security; |
356 | struct dentry *root = sb->s_root; | 356 | struct dentry *root = sb->s_root; |
357 | struct inode *root_inode = root->d_inode; | 357 | struct inode *root_inode = root->d_inode; |
358 | int rc = 0; | 358 | int rc = 0; |
359 | 359 | ||
360 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { | 360 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { |
361 | /* Make sure that the xattr handler exists and that no | 361 | /* Make sure that the xattr handler exists and that no |
362 | error other than -ENODATA is returned by getxattr on | 362 | error other than -ENODATA is returned by getxattr on |
363 | the root directory. -ENODATA is ok, as this may be | 363 | the root directory. -ENODATA is ok, as this may be |
364 | the first boot of the SELinux kernel before we have | 364 | the first boot of the SELinux kernel before we have |
365 | assigned xattr values to the filesystem. */ | 365 | assigned xattr values to the filesystem. */ |
366 | if (!root_inode->i_op->getxattr) { | 366 | if (!root_inode->i_op->getxattr) { |
367 | printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " | 367 | printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " |
368 | "xattr support\n", sb->s_id, sb->s_type->name); | 368 | "xattr support\n", sb->s_id, sb->s_type->name); |
369 | rc = -EOPNOTSUPP; | 369 | rc = -EOPNOTSUPP; |
370 | goto out; | 370 | goto out; |
371 | } | 371 | } |
372 | rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); | 372 | rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); |
373 | if (rc < 0 && rc != -ENODATA) { | 373 | if (rc < 0 && rc != -ENODATA) { |
374 | if (rc == -EOPNOTSUPP) | 374 | if (rc == -EOPNOTSUPP) |
375 | printk(KERN_WARNING "SELinux: (dev %s, type " | 375 | printk(KERN_WARNING "SELinux: (dev %s, type " |
376 | "%s) has no security xattr handler\n", | 376 | "%s) has no security xattr handler\n", |
377 | sb->s_id, sb->s_type->name); | 377 | sb->s_id, sb->s_type->name); |
378 | else | 378 | else |
379 | printk(KERN_WARNING "SELinux: (dev %s, type " | 379 | printk(KERN_WARNING "SELinux: (dev %s, type " |
380 | "%s) getxattr errno %d\n", sb->s_id, | 380 | "%s) getxattr errno %d\n", sb->s_id, |
381 | sb->s_type->name, -rc); | 381 | sb->s_type->name, -rc); |
382 | goto out; | 382 | goto out; |
383 | } | 383 | } |
384 | } | 384 | } |
385 | 385 | ||
386 | sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP); | 386 | sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP); |
387 | 387 | ||
388 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 388 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
389 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", | 389 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", |
390 | sb->s_id, sb->s_type->name); | 390 | sb->s_id, sb->s_type->name); |
391 | else | 391 | else |
392 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", | 392 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", |
393 | sb->s_id, sb->s_type->name, | 393 | sb->s_id, sb->s_type->name, |
394 | labeling_behaviors[sbsec->behavior-1]); | 394 | labeling_behaviors[sbsec->behavior-1]); |
395 | 395 | ||
396 | if (sbsec->behavior == SECURITY_FS_USE_GENFS || | 396 | if (sbsec->behavior == SECURITY_FS_USE_GENFS || |
397 | sbsec->behavior == SECURITY_FS_USE_MNTPOINT || | 397 | sbsec->behavior == SECURITY_FS_USE_MNTPOINT || |
398 | sbsec->behavior == SECURITY_FS_USE_NONE || | 398 | sbsec->behavior == SECURITY_FS_USE_NONE || |
399 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 399 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
400 | sbsec->flags &= ~SE_SBLABELSUPP; | 400 | sbsec->flags &= ~SE_SBLABELSUPP; |
401 | 401 | ||
402 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | 402 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ |
403 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | 403 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) |
404 | sbsec->flags |= SE_SBLABELSUPP; | 404 | sbsec->flags |= SE_SBLABELSUPP; |
405 | 405 | ||
406 | /* Initialize the root inode. */ | 406 | /* Initialize the root inode. */ |
407 | rc = inode_doinit_with_dentry(root_inode, root); | 407 | rc = inode_doinit_with_dentry(root_inode, root); |
408 | 408 | ||
409 | /* Initialize any other inodes associated with the superblock, e.g. | 409 | /* Initialize any other inodes associated with the superblock, e.g. |
410 | inodes created prior to initial policy load or inodes created | 410 | inodes created prior to initial policy load or inodes created |
411 | during get_sb by a pseudo filesystem that directly | 411 | during get_sb by a pseudo filesystem that directly |
412 | populates itself. */ | 412 | populates itself. */ |
413 | spin_lock(&sbsec->isec_lock); | 413 | spin_lock(&sbsec->isec_lock); |
414 | next_inode: | 414 | next_inode: |
415 | if (!list_empty(&sbsec->isec_head)) { | 415 | if (!list_empty(&sbsec->isec_head)) { |
416 | struct inode_security_struct *isec = | 416 | struct inode_security_struct *isec = |
417 | list_entry(sbsec->isec_head.next, | 417 | list_entry(sbsec->isec_head.next, |
418 | struct inode_security_struct, list); | 418 | struct inode_security_struct, list); |
419 | struct inode *inode = isec->inode; | 419 | struct inode *inode = isec->inode; |
420 | spin_unlock(&sbsec->isec_lock); | 420 | spin_unlock(&sbsec->isec_lock); |
421 | inode = igrab(inode); | 421 | inode = igrab(inode); |
422 | if (inode) { | 422 | if (inode) { |
423 | if (!IS_PRIVATE(inode)) | 423 | if (!IS_PRIVATE(inode)) |
424 | inode_doinit(inode); | 424 | inode_doinit(inode); |
425 | iput(inode); | 425 | iput(inode); |
426 | } | 426 | } |
427 | spin_lock(&sbsec->isec_lock); | 427 | spin_lock(&sbsec->isec_lock); |
428 | list_del_init(&isec->list); | 428 | list_del_init(&isec->list); |
429 | goto next_inode; | 429 | goto next_inode; |
430 | } | 430 | } |
431 | spin_unlock(&sbsec->isec_lock); | 431 | spin_unlock(&sbsec->isec_lock); |
432 | out: | 432 | out: |
433 | return rc; | 433 | return rc; |
434 | } | 434 | } |
435 | 435 | ||
436 | /* | 436 | /* |
437 | * This function should allow an FS to ask what it's mount security | 437 | * This function should allow an FS to ask what it's mount security |
438 | * options were so it can use those later for submounts, displaying | 438 | * options were so it can use those later for submounts, displaying |
439 | * mount options, or whatever. | 439 | * mount options, or whatever. |
440 | */ | 440 | */ |
441 | static int selinux_get_mnt_opts(const struct super_block *sb, | 441 | static int selinux_get_mnt_opts(const struct super_block *sb, |
442 | struct security_mnt_opts *opts) | 442 | struct security_mnt_opts *opts) |
443 | { | 443 | { |
444 | int rc = 0, i; | 444 | int rc = 0, i; |
445 | struct superblock_security_struct *sbsec = sb->s_security; | 445 | struct superblock_security_struct *sbsec = sb->s_security; |
446 | char *context = NULL; | 446 | char *context = NULL; |
447 | u32 len; | 447 | u32 len; |
448 | char tmp; | 448 | char tmp; |
449 | 449 | ||
450 | security_init_mnt_opts(opts); | 450 | security_init_mnt_opts(opts); |
451 | 451 | ||
452 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 452 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
453 | return -EINVAL; | 453 | return -EINVAL; |
454 | 454 | ||
455 | if (!ss_initialized) | 455 | if (!ss_initialized) |
456 | return -EINVAL; | 456 | return -EINVAL; |
457 | 457 | ||
458 | tmp = sbsec->flags & SE_MNTMASK; | 458 | tmp = sbsec->flags & SE_MNTMASK; |
459 | /* count the number of mount options for this sb */ | 459 | /* count the number of mount options for this sb */ |
460 | for (i = 0; i < 8; i++) { | 460 | for (i = 0; i < 8; i++) { |
461 | if (tmp & 0x01) | 461 | if (tmp & 0x01) |
462 | opts->num_mnt_opts++; | 462 | opts->num_mnt_opts++; |
463 | tmp >>= 1; | 463 | tmp >>= 1; |
464 | } | 464 | } |
465 | /* Check if the Label support flag is set */ | 465 | /* Check if the Label support flag is set */ |
466 | if (sbsec->flags & SE_SBLABELSUPP) | 466 | if (sbsec->flags & SE_SBLABELSUPP) |
467 | opts->num_mnt_opts++; | 467 | opts->num_mnt_opts++; |
468 | 468 | ||
469 | opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); | 469 | opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); |
470 | if (!opts->mnt_opts) { | 470 | if (!opts->mnt_opts) { |
471 | rc = -ENOMEM; | 471 | rc = -ENOMEM; |
472 | goto out_free; | 472 | goto out_free; |
473 | } | 473 | } |
474 | 474 | ||
475 | opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC); | 475 | opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC); |
476 | if (!opts->mnt_opts_flags) { | 476 | if (!opts->mnt_opts_flags) { |
477 | rc = -ENOMEM; | 477 | rc = -ENOMEM; |
478 | goto out_free; | 478 | goto out_free; |
479 | } | 479 | } |
480 | 480 | ||
481 | i = 0; | 481 | i = 0; |
482 | if (sbsec->flags & FSCONTEXT_MNT) { | 482 | if (sbsec->flags & FSCONTEXT_MNT) { |
483 | rc = security_sid_to_context(sbsec->sid, &context, &len); | 483 | rc = security_sid_to_context(sbsec->sid, &context, &len); |
484 | if (rc) | 484 | if (rc) |
485 | goto out_free; | 485 | goto out_free; |
486 | opts->mnt_opts[i] = context; | 486 | opts->mnt_opts[i] = context; |
487 | opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; | 487 | opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; |
488 | } | 488 | } |
489 | if (sbsec->flags & CONTEXT_MNT) { | 489 | if (sbsec->flags & CONTEXT_MNT) { |
490 | rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); | 490 | rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); |
491 | if (rc) | 491 | if (rc) |
492 | goto out_free; | 492 | goto out_free; |
493 | opts->mnt_opts[i] = context; | 493 | opts->mnt_opts[i] = context; |
494 | opts->mnt_opts_flags[i++] = CONTEXT_MNT; | 494 | opts->mnt_opts_flags[i++] = CONTEXT_MNT; |
495 | } | 495 | } |
496 | if (sbsec->flags & DEFCONTEXT_MNT) { | 496 | if (sbsec->flags & DEFCONTEXT_MNT) { |
497 | rc = security_sid_to_context(sbsec->def_sid, &context, &len); | 497 | rc = security_sid_to_context(sbsec->def_sid, &context, &len); |
498 | if (rc) | 498 | if (rc) |
499 | goto out_free; | 499 | goto out_free; |
500 | opts->mnt_opts[i] = context; | 500 | opts->mnt_opts[i] = context; |
501 | opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; | 501 | opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; |
502 | } | 502 | } |
503 | if (sbsec->flags & ROOTCONTEXT_MNT) { | 503 | if (sbsec->flags & ROOTCONTEXT_MNT) { |
504 | struct inode *root = sbsec->sb->s_root->d_inode; | 504 | struct inode *root = sbsec->sb->s_root->d_inode; |
505 | struct inode_security_struct *isec = root->i_security; | 505 | struct inode_security_struct *isec = root->i_security; |
506 | 506 | ||
507 | rc = security_sid_to_context(isec->sid, &context, &len); | 507 | rc = security_sid_to_context(isec->sid, &context, &len); |
508 | if (rc) | 508 | if (rc) |
509 | goto out_free; | 509 | goto out_free; |
510 | opts->mnt_opts[i] = context; | 510 | opts->mnt_opts[i] = context; |
511 | opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; | 511 | opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; |
512 | } | 512 | } |
513 | if (sbsec->flags & SE_SBLABELSUPP) { | 513 | if (sbsec->flags & SE_SBLABELSUPP) { |
514 | opts->mnt_opts[i] = NULL; | 514 | opts->mnt_opts[i] = NULL; |
515 | opts->mnt_opts_flags[i++] = SE_SBLABELSUPP; | 515 | opts->mnt_opts_flags[i++] = SE_SBLABELSUPP; |
516 | } | 516 | } |
517 | 517 | ||
518 | BUG_ON(i != opts->num_mnt_opts); | 518 | BUG_ON(i != opts->num_mnt_opts); |
519 | 519 | ||
520 | return 0; | 520 | return 0; |
521 | 521 | ||
522 | out_free: | 522 | out_free: |
523 | security_free_mnt_opts(opts); | 523 | security_free_mnt_opts(opts); |
524 | return rc; | 524 | return rc; |
525 | } | 525 | } |
526 | 526 | ||
527 | static int bad_option(struct superblock_security_struct *sbsec, char flag, | 527 | static int bad_option(struct superblock_security_struct *sbsec, char flag, |
528 | u32 old_sid, u32 new_sid) | 528 | u32 old_sid, u32 new_sid) |
529 | { | 529 | { |
530 | char mnt_flags = sbsec->flags & SE_MNTMASK; | 530 | char mnt_flags = sbsec->flags & SE_MNTMASK; |
531 | 531 | ||
532 | /* check if the old mount command had the same options */ | 532 | /* check if the old mount command had the same options */ |
533 | if (sbsec->flags & SE_SBINITIALIZED) | 533 | if (sbsec->flags & SE_SBINITIALIZED) |
534 | if (!(sbsec->flags & flag) || | 534 | if (!(sbsec->flags & flag) || |
535 | (old_sid != new_sid)) | 535 | (old_sid != new_sid)) |
536 | return 1; | 536 | return 1; |
537 | 537 | ||
538 | /* check if we were passed the same options twice, | 538 | /* check if we were passed the same options twice, |
539 | * aka someone passed context=a,context=b | 539 | * aka someone passed context=a,context=b |
540 | */ | 540 | */ |
541 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 541 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
542 | if (mnt_flags & flag) | 542 | if (mnt_flags & flag) |
543 | return 1; | 543 | return 1; |
544 | return 0; | 544 | return 0; |
545 | } | 545 | } |
546 | 546 | ||
547 | /* | 547 | /* |
548 | * Allow filesystems with binary mount data to explicitly set mount point | 548 | * Allow filesystems with binary mount data to explicitly set mount point |
549 | * labeling information. | 549 | * labeling information. |
550 | */ | 550 | */ |
551 | static int selinux_set_mnt_opts(struct super_block *sb, | 551 | static int selinux_set_mnt_opts(struct super_block *sb, |
552 | struct security_mnt_opts *opts) | 552 | struct security_mnt_opts *opts) |
553 | { | 553 | { |
554 | const struct cred *cred = current_cred(); | 554 | const struct cred *cred = current_cred(); |
555 | int rc = 0, i; | 555 | int rc = 0, i; |
556 | struct superblock_security_struct *sbsec = sb->s_security; | 556 | struct superblock_security_struct *sbsec = sb->s_security; |
557 | const char *name = sb->s_type->name; | 557 | const char *name = sb->s_type->name; |
558 | struct inode *inode = sbsec->sb->s_root->d_inode; | 558 | struct inode *inode = sbsec->sb->s_root->d_inode; |
559 | struct inode_security_struct *root_isec = inode->i_security; | 559 | struct inode_security_struct *root_isec = inode->i_security; |
560 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 560 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
561 | u32 defcontext_sid = 0; | 561 | u32 defcontext_sid = 0; |
562 | char **mount_options = opts->mnt_opts; | 562 | char **mount_options = opts->mnt_opts; |
563 | int *flags = opts->mnt_opts_flags; | 563 | int *flags = opts->mnt_opts_flags; |
564 | int num_opts = opts->num_mnt_opts; | 564 | int num_opts = opts->num_mnt_opts; |
565 | 565 | ||
566 | mutex_lock(&sbsec->lock); | 566 | mutex_lock(&sbsec->lock); |
567 | 567 | ||
568 | if (!ss_initialized) { | 568 | if (!ss_initialized) { |
569 | if (!num_opts) { | 569 | if (!num_opts) { |
570 | /* Defer initialization until selinux_complete_init, | 570 | /* Defer initialization until selinux_complete_init, |
571 | after the initial policy is loaded and the security | 571 | after the initial policy is loaded and the security |
572 | server is ready to handle calls. */ | 572 | server is ready to handle calls. */ |
573 | goto out; | 573 | goto out; |
574 | } | 574 | } |
575 | rc = -EINVAL; | 575 | rc = -EINVAL; |
576 | printk(KERN_WARNING "SELinux: Unable to set superblock options " | 576 | printk(KERN_WARNING "SELinux: Unable to set superblock options " |
577 | "before the security server is initialized\n"); | 577 | "before the security server is initialized\n"); |
578 | goto out; | 578 | goto out; |
579 | } | 579 | } |
580 | 580 | ||
581 | /* | 581 | /* |
582 | * Binary mount data FS will come through this function twice. Once | 582 | * Binary mount data FS will come through this function twice. Once |
583 | * from an explicit call and once from the generic calls from the vfs. | 583 | * from an explicit call and once from the generic calls from the vfs. |
584 | * Since the generic VFS calls will not contain any security mount data | 584 | * Since the generic VFS calls will not contain any security mount data |
585 | * we need to skip the double mount verification. | 585 | * we need to skip the double mount verification. |
586 | * | 586 | * |
587 | * This does open a hole in which we will not notice if the first | 587 | * This does open a hole in which we will not notice if the first |
588 | * mount using this sb set explict options and a second mount using | 588 | * mount using this sb set explict options and a second mount using |
589 | * this sb does not set any security options. (The first options | 589 | * this sb does not set any security options. (The first options |
590 | * will be used for both mounts) | 590 | * will be used for both mounts) |
591 | */ | 591 | */ |
592 | if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) | 592 | if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) |
593 | && (num_opts == 0)) | 593 | && (num_opts == 0)) |
594 | goto out; | 594 | goto out; |
595 | 595 | ||
596 | /* | 596 | /* |
597 | * parse the mount options, check if they are valid sids. | 597 | * parse the mount options, check if they are valid sids. |
598 | * also check if someone is trying to mount the same sb more | 598 | * also check if someone is trying to mount the same sb more |
599 | * than once with different security options. | 599 | * than once with different security options. |
600 | */ | 600 | */ |
601 | for (i = 0; i < num_opts; i++) { | 601 | for (i = 0; i < num_opts; i++) { |
602 | u32 sid; | 602 | u32 sid; |
603 | 603 | ||
604 | if (flags[i] == SE_SBLABELSUPP) | 604 | if (flags[i] == SE_SBLABELSUPP) |
605 | continue; | 605 | continue; |
606 | rc = security_context_to_sid(mount_options[i], | 606 | rc = security_context_to_sid(mount_options[i], |
607 | strlen(mount_options[i]), &sid); | 607 | strlen(mount_options[i]), &sid); |
608 | if (rc) { | 608 | if (rc) { |
609 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 609 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
610 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 610 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
611 | mount_options[i], sb->s_id, name, rc); | 611 | mount_options[i], sb->s_id, name, rc); |
612 | goto out; | 612 | goto out; |
613 | } | 613 | } |
614 | switch (flags[i]) { | 614 | switch (flags[i]) { |
615 | case FSCONTEXT_MNT: | 615 | case FSCONTEXT_MNT: |
616 | fscontext_sid = sid; | 616 | fscontext_sid = sid; |
617 | 617 | ||
618 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, | 618 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, |
619 | fscontext_sid)) | 619 | fscontext_sid)) |
620 | goto out_double_mount; | 620 | goto out_double_mount; |
621 | 621 | ||
622 | sbsec->flags |= FSCONTEXT_MNT; | 622 | sbsec->flags |= FSCONTEXT_MNT; |
623 | break; | 623 | break; |
624 | case CONTEXT_MNT: | 624 | case CONTEXT_MNT: |
625 | context_sid = sid; | 625 | context_sid = sid; |
626 | 626 | ||
627 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, | 627 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, |
628 | context_sid)) | 628 | context_sid)) |
629 | goto out_double_mount; | 629 | goto out_double_mount; |
630 | 630 | ||
631 | sbsec->flags |= CONTEXT_MNT; | 631 | sbsec->flags |= CONTEXT_MNT; |
632 | break; | 632 | break; |
633 | case ROOTCONTEXT_MNT: | 633 | case ROOTCONTEXT_MNT: |
634 | rootcontext_sid = sid; | 634 | rootcontext_sid = sid; |
635 | 635 | ||
636 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, | 636 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, |
637 | rootcontext_sid)) | 637 | rootcontext_sid)) |
638 | goto out_double_mount; | 638 | goto out_double_mount; |
639 | 639 | ||
640 | sbsec->flags |= ROOTCONTEXT_MNT; | 640 | sbsec->flags |= ROOTCONTEXT_MNT; |
641 | 641 | ||
642 | break; | 642 | break; |
643 | case DEFCONTEXT_MNT: | 643 | case DEFCONTEXT_MNT: |
644 | defcontext_sid = sid; | 644 | defcontext_sid = sid; |
645 | 645 | ||
646 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, | 646 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, |
647 | defcontext_sid)) | 647 | defcontext_sid)) |
648 | goto out_double_mount; | 648 | goto out_double_mount; |
649 | 649 | ||
650 | sbsec->flags |= DEFCONTEXT_MNT; | 650 | sbsec->flags |= DEFCONTEXT_MNT; |
651 | 651 | ||
652 | break; | 652 | break; |
653 | default: | 653 | default: |
654 | rc = -EINVAL; | 654 | rc = -EINVAL; |
655 | goto out; | 655 | goto out; |
656 | } | 656 | } |
657 | } | 657 | } |
658 | 658 | ||
659 | if (sbsec->flags & SE_SBINITIALIZED) { | 659 | if (sbsec->flags & SE_SBINITIALIZED) { |
660 | /* previously mounted with options, but not on this attempt? */ | 660 | /* previously mounted with options, but not on this attempt? */ |
661 | if ((sbsec->flags & SE_MNTMASK) && !num_opts) | 661 | if ((sbsec->flags & SE_MNTMASK) && !num_opts) |
662 | goto out_double_mount; | 662 | goto out_double_mount; |
663 | rc = 0; | 663 | rc = 0; |
664 | goto out; | 664 | goto out; |
665 | } | 665 | } |
666 | 666 | ||
667 | if (strcmp(sb->s_type->name, "proc") == 0) | 667 | if (strcmp(sb->s_type->name, "proc") == 0) |
668 | sbsec->flags |= SE_SBPROC; | 668 | sbsec->flags |= SE_SBPROC; |
669 | 669 | ||
670 | /* Determine the labeling behavior to use for this filesystem type. */ | 670 | /* Determine the labeling behavior to use for this filesystem type. */ |
671 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); | 671 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); |
672 | if (rc) { | 672 | if (rc) { |
673 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | 673 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", |
674 | __func__, sb->s_type->name, rc); | 674 | __func__, sb->s_type->name, rc); |
675 | goto out; | 675 | goto out; |
676 | } | 676 | } |
677 | 677 | ||
678 | /* sets the context of the superblock for the fs being mounted. */ | 678 | /* sets the context of the superblock for the fs being mounted. */ |
679 | if (fscontext_sid) { | 679 | if (fscontext_sid) { |
680 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); | 680 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); |
681 | if (rc) | 681 | if (rc) |
682 | goto out; | 682 | goto out; |
683 | 683 | ||
684 | sbsec->sid = fscontext_sid; | 684 | sbsec->sid = fscontext_sid; |
685 | } | 685 | } |
686 | 686 | ||
687 | /* | 687 | /* |
688 | * Switch to using mount point labeling behavior. | 688 | * Switch to using mount point labeling behavior. |
689 | * sets the label used on all file below the mountpoint, and will set | 689 | * sets the label used on all file below the mountpoint, and will set |
690 | * the superblock context if not already set. | 690 | * the superblock context if not already set. |
691 | */ | 691 | */ |
692 | if (context_sid) { | 692 | if (context_sid) { |
693 | if (!fscontext_sid) { | 693 | if (!fscontext_sid) { |
694 | rc = may_context_mount_sb_relabel(context_sid, sbsec, | 694 | rc = may_context_mount_sb_relabel(context_sid, sbsec, |
695 | cred); | 695 | cred); |
696 | if (rc) | 696 | if (rc) |
697 | goto out; | 697 | goto out; |
698 | sbsec->sid = context_sid; | 698 | sbsec->sid = context_sid; |
699 | } else { | 699 | } else { |
700 | rc = may_context_mount_inode_relabel(context_sid, sbsec, | 700 | rc = may_context_mount_inode_relabel(context_sid, sbsec, |
701 | cred); | 701 | cred); |
702 | if (rc) | 702 | if (rc) |
703 | goto out; | 703 | goto out; |
704 | } | 704 | } |
705 | if (!rootcontext_sid) | 705 | if (!rootcontext_sid) |
706 | rootcontext_sid = context_sid; | 706 | rootcontext_sid = context_sid; |
707 | 707 | ||
708 | sbsec->mntpoint_sid = context_sid; | 708 | sbsec->mntpoint_sid = context_sid; |
709 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; | 709 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; |
710 | } | 710 | } |
711 | 711 | ||
712 | if (rootcontext_sid) { | 712 | if (rootcontext_sid) { |
713 | rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, | 713 | rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, |
714 | cred); | 714 | cred); |
715 | if (rc) | 715 | if (rc) |
716 | goto out; | 716 | goto out; |
717 | 717 | ||
718 | root_isec->sid = rootcontext_sid; | 718 | root_isec->sid = rootcontext_sid; |
719 | root_isec->initialized = 1; | 719 | root_isec->initialized = 1; |
720 | } | 720 | } |
721 | 721 | ||
722 | if (defcontext_sid) { | 722 | if (defcontext_sid) { |
723 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 723 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { |
724 | rc = -EINVAL; | 724 | rc = -EINVAL; |
725 | printk(KERN_WARNING "SELinux: defcontext option is " | 725 | printk(KERN_WARNING "SELinux: defcontext option is " |
726 | "invalid for this filesystem type\n"); | 726 | "invalid for this filesystem type\n"); |
727 | goto out; | 727 | goto out; |
728 | } | 728 | } |
729 | 729 | ||
730 | if (defcontext_sid != sbsec->def_sid) { | 730 | if (defcontext_sid != sbsec->def_sid) { |
731 | rc = may_context_mount_inode_relabel(defcontext_sid, | 731 | rc = may_context_mount_inode_relabel(defcontext_sid, |
732 | sbsec, cred); | 732 | sbsec, cred); |
733 | if (rc) | 733 | if (rc) |
734 | goto out; | 734 | goto out; |
735 | } | 735 | } |
736 | 736 | ||
737 | sbsec->def_sid = defcontext_sid; | 737 | sbsec->def_sid = defcontext_sid; |
738 | } | 738 | } |
739 | 739 | ||
740 | rc = sb_finish_set_opts(sb); | 740 | rc = sb_finish_set_opts(sb); |
741 | out: | 741 | out: |
742 | mutex_unlock(&sbsec->lock); | 742 | mutex_unlock(&sbsec->lock); |
743 | return rc; | 743 | return rc; |
744 | out_double_mount: | 744 | out_double_mount: |
745 | rc = -EINVAL; | 745 | rc = -EINVAL; |
746 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " | 746 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " |
747 | "security settings for (dev %s, type %s)\n", sb->s_id, name); | 747 | "security settings for (dev %s, type %s)\n", sb->s_id, name); |
748 | goto out; | 748 | goto out; |
749 | } | 749 | } |
750 | 750 | ||
751 | static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | 751 | static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, |
752 | struct super_block *newsb) | 752 | struct super_block *newsb) |
753 | { | 753 | { |
754 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; | 754 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; |
755 | struct superblock_security_struct *newsbsec = newsb->s_security; | 755 | struct superblock_security_struct *newsbsec = newsb->s_security; |
756 | 756 | ||
757 | int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT); | 757 | int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT); |
758 | int set_context = (oldsbsec->flags & CONTEXT_MNT); | 758 | int set_context = (oldsbsec->flags & CONTEXT_MNT); |
759 | int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT); | 759 | int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT); |
760 | 760 | ||
761 | /* | 761 | /* |
762 | * if the parent was able to be mounted it clearly had no special lsm | 762 | * if the parent was able to be mounted it clearly had no special lsm |
763 | * mount options. thus we can safely deal with this superblock later | 763 | * mount options. thus we can safely deal with this superblock later |
764 | */ | 764 | */ |
765 | if (!ss_initialized) | 765 | if (!ss_initialized) |
766 | return; | 766 | return; |
767 | 767 | ||
768 | /* how can we clone if the old one wasn't set up?? */ | 768 | /* how can we clone if the old one wasn't set up?? */ |
769 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 769 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
770 | 770 | ||
771 | /* if fs is reusing a sb, just let its options stand... */ | 771 | /* if fs is reusing a sb, just let its options stand... */ |
772 | if (newsbsec->flags & SE_SBINITIALIZED) | 772 | if (newsbsec->flags & SE_SBINITIALIZED) |
773 | return; | 773 | return; |
774 | 774 | ||
775 | mutex_lock(&newsbsec->lock); | 775 | mutex_lock(&newsbsec->lock); |
776 | 776 | ||
777 | newsbsec->flags = oldsbsec->flags; | 777 | newsbsec->flags = oldsbsec->flags; |
778 | 778 | ||
779 | newsbsec->sid = oldsbsec->sid; | 779 | newsbsec->sid = oldsbsec->sid; |
780 | newsbsec->def_sid = oldsbsec->def_sid; | 780 | newsbsec->def_sid = oldsbsec->def_sid; |
781 | newsbsec->behavior = oldsbsec->behavior; | 781 | newsbsec->behavior = oldsbsec->behavior; |
782 | 782 | ||
783 | if (set_context) { | 783 | if (set_context) { |
784 | u32 sid = oldsbsec->mntpoint_sid; | 784 | u32 sid = oldsbsec->mntpoint_sid; |
785 | 785 | ||
786 | if (!set_fscontext) | 786 | if (!set_fscontext) |
787 | newsbsec->sid = sid; | 787 | newsbsec->sid = sid; |
788 | if (!set_rootcontext) { | 788 | if (!set_rootcontext) { |
789 | struct inode *newinode = newsb->s_root->d_inode; | 789 | struct inode *newinode = newsb->s_root->d_inode; |
790 | struct inode_security_struct *newisec = newinode->i_security; | 790 | struct inode_security_struct *newisec = newinode->i_security; |
791 | newisec->sid = sid; | 791 | newisec->sid = sid; |
792 | } | 792 | } |
793 | newsbsec->mntpoint_sid = sid; | 793 | newsbsec->mntpoint_sid = sid; |
794 | } | 794 | } |
795 | if (set_rootcontext) { | 795 | if (set_rootcontext) { |
796 | const struct inode *oldinode = oldsb->s_root->d_inode; | 796 | const struct inode *oldinode = oldsb->s_root->d_inode; |
797 | const struct inode_security_struct *oldisec = oldinode->i_security; | 797 | const struct inode_security_struct *oldisec = oldinode->i_security; |
798 | struct inode *newinode = newsb->s_root->d_inode; | 798 | struct inode *newinode = newsb->s_root->d_inode; |
799 | struct inode_security_struct *newisec = newinode->i_security; | 799 | struct inode_security_struct *newisec = newinode->i_security; |
800 | 800 | ||
801 | newisec->sid = oldisec->sid; | 801 | newisec->sid = oldisec->sid; |
802 | } | 802 | } |
803 | 803 | ||
804 | sb_finish_set_opts(newsb); | 804 | sb_finish_set_opts(newsb); |
805 | mutex_unlock(&newsbsec->lock); | 805 | mutex_unlock(&newsbsec->lock); |
806 | } | 806 | } |
807 | 807 | ||
808 | static int selinux_parse_opts_str(char *options, | 808 | static int selinux_parse_opts_str(char *options, |
809 | struct security_mnt_opts *opts) | 809 | struct security_mnt_opts *opts) |
810 | { | 810 | { |
811 | char *p; | 811 | char *p; |
812 | char *context = NULL, *defcontext = NULL; | 812 | char *context = NULL, *defcontext = NULL; |
813 | char *fscontext = NULL, *rootcontext = NULL; | 813 | char *fscontext = NULL, *rootcontext = NULL; |
814 | int rc, num_mnt_opts = 0; | 814 | int rc, num_mnt_opts = 0; |
815 | 815 | ||
816 | opts->num_mnt_opts = 0; | 816 | opts->num_mnt_opts = 0; |
817 | 817 | ||
818 | /* Standard string-based options. */ | 818 | /* Standard string-based options. */ |
819 | while ((p = strsep(&options, "|")) != NULL) { | 819 | while ((p = strsep(&options, "|")) != NULL) { |
820 | int token; | 820 | int token; |
821 | substring_t args[MAX_OPT_ARGS]; | 821 | substring_t args[MAX_OPT_ARGS]; |
822 | 822 | ||
823 | if (!*p) | 823 | if (!*p) |
824 | continue; | 824 | continue; |
825 | 825 | ||
826 | token = match_token(p, tokens, args); | 826 | token = match_token(p, tokens, args); |
827 | 827 | ||
828 | switch (token) { | 828 | switch (token) { |
829 | case Opt_context: | 829 | case Opt_context: |
830 | if (context || defcontext) { | 830 | if (context || defcontext) { |
831 | rc = -EINVAL; | 831 | rc = -EINVAL; |
832 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 832 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
833 | goto out_err; | 833 | goto out_err; |
834 | } | 834 | } |
835 | context = match_strdup(&args[0]); | 835 | context = match_strdup(&args[0]); |
836 | if (!context) { | 836 | if (!context) { |
837 | rc = -ENOMEM; | 837 | rc = -ENOMEM; |
838 | goto out_err; | 838 | goto out_err; |
839 | } | 839 | } |
840 | break; | 840 | break; |
841 | 841 | ||
842 | case Opt_fscontext: | 842 | case Opt_fscontext: |
843 | if (fscontext) { | 843 | if (fscontext) { |
844 | rc = -EINVAL; | 844 | rc = -EINVAL; |
845 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 845 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
846 | goto out_err; | 846 | goto out_err; |
847 | } | 847 | } |
848 | fscontext = match_strdup(&args[0]); | 848 | fscontext = match_strdup(&args[0]); |
849 | if (!fscontext) { | 849 | if (!fscontext) { |
850 | rc = -ENOMEM; | 850 | rc = -ENOMEM; |
851 | goto out_err; | 851 | goto out_err; |
852 | } | 852 | } |
853 | break; | 853 | break; |
854 | 854 | ||
855 | case Opt_rootcontext: | 855 | case Opt_rootcontext: |
856 | if (rootcontext) { | 856 | if (rootcontext) { |
857 | rc = -EINVAL; | 857 | rc = -EINVAL; |
858 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 858 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
859 | goto out_err; | 859 | goto out_err; |
860 | } | 860 | } |
861 | rootcontext = match_strdup(&args[0]); | 861 | rootcontext = match_strdup(&args[0]); |
862 | if (!rootcontext) { | 862 | if (!rootcontext) { |
863 | rc = -ENOMEM; | 863 | rc = -ENOMEM; |
864 | goto out_err; | 864 | goto out_err; |
865 | } | 865 | } |
866 | break; | 866 | break; |
867 | 867 | ||
868 | case Opt_defcontext: | 868 | case Opt_defcontext: |
869 | if (context || defcontext) { | 869 | if (context || defcontext) { |
870 | rc = -EINVAL; | 870 | rc = -EINVAL; |
871 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 871 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
872 | goto out_err; | 872 | goto out_err; |
873 | } | 873 | } |
874 | defcontext = match_strdup(&args[0]); | 874 | defcontext = match_strdup(&args[0]); |
875 | if (!defcontext) { | 875 | if (!defcontext) { |
876 | rc = -ENOMEM; | 876 | rc = -ENOMEM; |
877 | goto out_err; | 877 | goto out_err; |
878 | } | 878 | } |
879 | break; | 879 | break; |
880 | case Opt_labelsupport: | 880 | case Opt_labelsupport: |
881 | break; | 881 | break; |
882 | default: | 882 | default: |
883 | rc = -EINVAL; | 883 | rc = -EINVAL; |
884 | printk(KERN_WARNING "SELinux: unknown mount option\n"); | 884 | printk(KERN_WARNING "SELinux: unknown mount option\n"); |
885 | goto out_err; | 885 | goto out_err; |
886 | 886 | ||
887 | } | 887 | } |
888 | } | 888 | } |
889 | 889 | ||
890 | rc = -ENOMEM; | 890 | rc = -ENOMEM; |
891 | opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC); | 891 | opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC); |
892 | if (!opts->mnt_opts) | 892 | if (!opts->mnt_opts) |
893 | goto out_err; | 893 | goto out_err; |
894 | 894 | ||
895 | opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC); | 895 | opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC); |
896 | if (!opts->mnt_opts_flags) { | 896 | if (!opts->mnt_opts_flags) { |
897 | kfree(opts->mnt_opts); | 897 | kfree(opts->mnt_opts); |
898 | goto out_err; | 898 | goto out_err; |
899 | } | 899 | } |
900 | 900 | ||
901 | if (fscontext) { | 901 | if (fscontext) { |
902 | opts->mnt_opts[num_mnt_opts] = fscontext; | 902 | opts->mnt_opts[num_mnt_opts] = fscontext; |
903 | opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; | 903 | opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; |
904 | } | 904 | } |
905 | if (context) { | 905 | if (context) { |
906 | opts->mnt_opts[num_mnt_opts] = context; | 906 | opts->mnt_opts[num_mnt_opts] = context; |
907 | opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; | 907 | opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; |
908 | } | 908 | } |
909 | if (rootcontext) { | 909 | if (rootcontext) { |
910 | opts->mnt_opts[num_mnt_opts] = rootcontext; | 910 | opts->mnt_opts[num_mnt_opts] = rootcontext; |
911 | opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; | 911 | opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; |
912 | } | 912 | } |
913 | if (defcontext) { | 913 | if (defcontext) { |
914 | opts->mnt_opts[num_mnt_opts] = defcontext; | 914 | opts->mnt_opts[num_mnt_opts] = defcontext; |
915 | opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; | 915 | opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; |
916 | } | 916 | } |
917 | 917 | ||
918 | opts->num_mnt_opts = num_mnt_opts; | 918 | opts->num_mnt_opts = num_mnt_opts; |
919 | return 0; | 919 | return 0; |
920 | 920 | ||
921 | out_err: | 921 | out_err: |
922 | kfree(context); | 922 | kfree(context); |
923 | kfree(defcontext); | 923 | kfree(defcontext); |
924 | kfree(fscontext); | 924 | kfree(fscontext); |
925 | kfree(rootcontext); | 925 | kfree(rootcontext); |
926 | return rc; | 926 | return rc; |
927 | } | 927 | } |
928 | /* | 928 | /* |
929 | * string mount options parsing and call set the sbsec | 929 | * string mount options parsing and call set the sbsec |
930 | */ | 930 | */ |
931 | static int superblock_doinit(struct super_block *sb, void *data) | 931 | static int superblock_doinit(struct super_block *sb, void *data) |
932 | { | 932 | { |
933 | int rc = 0; | 933 | int rc = 0; |
934 | char *options = data; | 934 | char *options = data; |
935 | struct security_mnt_opts opts; | 935 | struct security_mnt_opts opts; |
936 | 936 | ||
937 | security_init_mnt_opts(&opts); | 937 | security_init_mnt_opts(&opts); |
938 | 938 | ||
939 | if (!data) | 939 | if (!data) |
940 | goto out; | 940 | goto out; |
941 | 941 | ||
942 | BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA); | 942 | BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA); |
943 | 943 | ||
944 | rc = selinux_parse_opts_str(options, &opts); | 944 | rc = selinux_parse_opts_str(options, &opts); |
945 | if (rc) | 945 | if (rc) |
946 | goto out_err; | 946 | goto out_err; |
947 | 947 | ||
948 | out: | 948 | out: |
949 | rc = selinux_set_mnt_opts(sb, &opts); | 949 | rc = selinux_set_mnt_opts(sb, &opts); |
950 | 950 | ||
951 | out_err: | 951 | out_err: |
952 | security_free_mnt_opts(&opts); | 952 | security_free_mnt_opts(&opts); |
953 | return rc; | 953 | return rc; |
954 | } | 954 | } |
955 | 955 | ||
956 | static void selinux_write_opts(struct seq_file *m, | 956 | static void selinux_write_opts(struct seq_file *m, |
957 | struct security_mnt_opts *opts) | 957 | struct security_mnt_opts *opts) |
958 | { | 958 | { |
959 | int i; | 959 | int i; |
960 | char *prefix; | 960 | char *prefix; |
961 | 961 | ||
962 | for (i = 0; i < opts->num_mnt_opts; i++) { | 962 | for (i = 0; i < opts->num_mnt_opts; i++) { |
963 | char *has_comma; | 963 | char *has_comma; |
964 | 964 | ||
965 | if (opts->mnt_opts[i]) | 965 | if (opts->mnt_opts[i]) |
966 | has_comma = strchr(opts->mnt_opts[i], ','); | 966 | has_comma = strchr(opts->mnt_opts[i], ','); |
967 | else | 967 | else |
968 | has_comma = NULL; | 968 | has_comma = NULL; |
969 | 969 | ||
970 | switch (opts->mnt_opts_flags[i]) { | 970 | switch (opts->mnt_opts_flags[i]) { |
971 | case CONTEXT_MNT: | 971 | case CONTEXT_MNT: |
972 | prefix = CONTEXT_STR; | 972 | prefix = CONTEXT_STR; |
973 | break; | 973 | break; |
974 | case FSCONTEXT_MNT: | 974 | case FSCONTEXT_MNT: |
975 | prefix = FSCONTEXT_STR; | 975 | prefix = FSCONTEXT_STR; |
976 | break; | 976 | break; |
977 | case ROOTCONTEXT_MNT: | 977 | case ROOTCONTEXT_MNT: |
978 | prefix = ROOTCONTEXT_STR; | 978 | prefix = ROOTCONTEXT_STR; |
979 | break; | 979 | break; |
980 | case DEFCONTEXT_MNT: | 980 | case DEFCONTEXT_MNT: |
981 | prefix = DEFCONTEXT_STR; | 981 | prefix = DEFCONTEXT_STR; |
982 | break; | 982 | break; |
983 | case SE_SBLABELSUPP: | 983 | case SE_SBLABELSUPP: |
984 | seq_putc(m, ','); | 984 | seq_putc(m, ','); |
985 | seq_puts(m, LABELSUPP_STR); | 985 | seq_puts(m, LABELSUPP_STR); |
986 | continue; | 986 | continue; |
987 | default: | 987 | default: |
988 | BUG(); | 988 | BUG(); |
989 | return; | 989 | return; |
990 | }; | 990 | }; |
991 | /* we need a comma before each option */ | 991 | /* we need a comma before each option */ |
992 | seq_putc(m, ','); | 992 | seq_putc(m, ','); |
993 | seq_puts(m, prefix); | 993 | seq_puts(m, prefix); |
994 | if (has_comma) | 994 | if (has_comma) |
995 | seq_putc(m, '\"'); | 995 | seq_putc(m, '\"'); |
996 | seq_puts(m, opts->mnt_opts[i]); | 996 | seq_puts(m, opts->mnt_opts[i]); |
997 | if (has_comma) | 997 | if (has_comma) |
998 | seq_putc(m, '\"'); | 998 | seq_putc(m, '\"'); |
999 | } | 999 | } |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) | 1002 | static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) |
1003 | { | 1003 | { |
1004 | struct security_mnt_opts opts; | 1004 | struct security_mnt_opts opts; |
1005 | int rc; | 1005 | int rc; |
1006 | 1006 | ||
1007 | rc = selinux_get_mnt_opts(sb, &opts); | 1007 | rc = selinux_get_mnt_opts(sb, &opts); |
1008 | if (rc) { | 1008 | if (rc) { |
1009 | /* before policy load we may get EINVAL, don't show anything */ | 1009 | /* before policy load we may get EINVAL, don't show anything */ |
1010 | if (rc == -EINVAL) | 1010 | if (rc == -EINVAL) |
1011 | rc = 0; | 1011 | rc = 0; |
1012 | return rc; | 1012 | return rc; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | selinux_write_opts(m, &opts); | 1015 | selinux_write_opts(m, &opts); |
1016 | 1016 | ||
1017 | security_free_mnt_opts(&opts); | 1017 | security_free_mnt_opts(&opts); |
1018 | 1018 | ||
1019 | return rc; | 1019 | return rc; |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | static inline u16 inode_mode_to_security_class(umode_t mode) | 1022 | static inline u16 inode_mode_to_security_class(umode_t mode) |
1023 | { | 1023 | { |
1024 | switch (mode & S_IFMT) { | 1024 | switch (mode & S_IFMT) { |
1025 | case S_IFSOCK: | 1025 | case S_IFSOCK: |
1026 | return SECCLASS_SOCK_FILE; | 1026 | return SECCLASS_SOCK_FILE; |
1027 | case S_IFLNK: | 1027 | case S_IFLNK: |
1028 | return SECCLASS_LNK_FILE; | 1028 | return SECCLASS_LNK_FILE; |
1029 | case S_IFREG: | 1029 | case S_IFREG: |
1030 | return SECCLASS_FILE; | 1030 | return SECCLASS_FILE; |
1031 | case S_IFBLK: | 1031 | case S_IFBLK: |
1032 | return SECCLASS_BLK_FILE; | 1032 | return SECCLASS_BLK_FILE; |
1033 | case S_IFDIR: | 1033 | case S_IFDIR: |
1034 | return SECCLASS_DIR; | 1034 | return SECCLASS_DIR; |
1035 | case S_IFCHR: | 1035 | case S_IFCHR: |
1036 | return SECCLASS_CHR_FILE; | 1036 | return SECCLASS_CHR_FILE; |
1037 | case S_IFIFO: | 1037 | case S_IFIFO: |
1038 | return SECCLASS_FIFO_FILE; | 1038 | return SECCLASS_FIFO_FILE; |
1039 | 1039 | ||
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | return SECCLASS_FILE; | 1042 | return SECCLASS_FILE; |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | static inline int default_protocol_stream(int protocol) | 1045 | static inline int default_protocol_stream(int protocol) |
1046 | { | 1046 | { |
1047 | return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP); | 1047 | return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP); |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | static inline int default_protocol_dgram(int protocol) | 1050 | static inline int default_protocol_dgram(int protocol) |
1051 | { | 1051 | { |
1052 | return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP); | 1052 | return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP); |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) | 1055 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) |
1056 | { | 1056 | { |
1057 | switch (family) { | 1057 | switch (family) { |
1058 | case PF_UNIX: | 1058 | case PF_UNIX: |
1059 | switch (type) { | 1059 | switch (type) { |
1060 | case SOCK_STREAM: | 1060 | case SOCK_STREAM: |
1061 | case SOCK_SEQPACKET: | 1061 | case SOCK_SEQPACKET: |
1062 | return SECCLASS_UNIX_STREAM_SOCKET; | 1062 | return SECCLASS_UNIX_STREAM_SOCKET; |
1063 | case SOCK_DGRAM: | 1063 | case SOCK_DGRAM: |
1064 | return SECCLASS_UNIX_DGRAM_SOCKET; | 1064 | return SECCLASS_UNIX_DGRAM_SOCKET; |
1065 | } | 1065 | } |
1066 | break; | 1066 | break; |
1067 | case PF_INET: | 1067 | case PF_INET: |
1068 | case PF_INET6: | 1068 | case PF_INET6: |
1069 | switch (type) { | 1069 | switch (type) { |
1070 | case SOCK_STREAM: | 1070 | case SOCK_STREAM: |
1071 | if (default_protocol_stream(protocol)) | 1071 | if (default_protocol_stream(protocol)) |
1072 | return SECCLASS_TCP_SOCKET; | 1072 | return SECCLASS_TCP_SOCKET; |
1073 | else | 1073 | else |
1074 | return SECCLASS_RAWIP_SOCKET; | 1074 | return SECCLASS_RAWIP_SOCKET; |
1075 | case SOCK_DGRAM: | 1075 | case SOCK_DGRAM: |
1076 | if (default_protocol_dgram(protocol)) | 1076 | if (default_protocol_dgram(protocol)) |
1077 | return SECCLASS_UDP_SOCKET; | 1077 | return SECCLASS_UDP_SOCKET; |
1078 | else | 1078 | else |
1079 | return SECCLASS_RAWIP_SOCKET; | 1079 | return SECCLASS_RAWIP_SOCKET; |
1080 | case SOCK_DCCP: | 1080 | case SOCK_DCCP: |
1081 | return SECCLASS_DCCP_SOCKET; | 1081 | return SECCLASS_DCCP_SOCKET; |
1082 | default: | 1082 | default: |
1083 | return SECCLASS_RAWIP_SOCKET; | 1083 | return SECCLASS_RAWIP_SOCKET; |
1084 | } | 1084 | } |
1085 | break; | 1085 | break; |
1086 | case PF_NETLINK: | 1086 | case PF_NETLINK: |
1087 | switch (protocol) { | 1087 | switch (protocol) { |
1088 | case NETLINK_ROUTE: | 1088 | case NETLINK_ROUTE: |
1089 | return SECCLASS_NETLINK_ROUTE_SOCKET; | 1089 | return SECCLASS_NETLINK_ROUTE_SOCKET; |
1090 | case NETLINK_FIREWALL: | 1090 | case NETLINK_FIREWALL: |
1091 | return SECCLASS_NETLINK_FIREWALL_SOCKET; | 1091 | return SECCLASS_NETLINK_FIREWALL_SOCKET; |
1092 | case NETLINK_INET_DIAG: | 1092 | case NETLINK_INET_DIAG: |
1093 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; | 1093 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; |
1094 | case NETLINK_NFLOG: | 1094 | case NETLINK_NFLOG: |
1095 | return SECCLASS_NETLINK_NFLOG_SOCKET; | 1095 | return SECCLASS_NETLINK_NFLOG_SOCKET; |
1096 | case NETLINK_XFRM: | 1096 | case NETLINK_XFRM: |
1097 | return SECCLASS_NETLINK_XFRM_SOCKET; | 1097 | return SECCLASS_NETLINK_XFRM_SOCKET; |
1098 | case NETLINK_SELINUX: | 1098 | case NETLINK_SELINUX: |
1099 | return SECCLASS_NETLINK_SELINUX_SOCKET; | 1099 | return SECCLASS_NETLINK_SELINUX_SOCKET; |
1100 | case NETLINK_AUDIT: | 1100 | case NETLINK_AUDIT: |
1101 | return SECCLASS_NETLINK_AUDIT_SOCKET; | 1101 | return SECCLASS_NETLINK_AUDIT_SOCKET; |
1102 | case NETLINK_IP6_FW: | 1102 | case NETLINK_IP6_FW: |
1103 | return SECCLASS_NETLINK_IP6FW_SOCKET; | 1103 | return SECCLASS_NETLINK_IP6FW_SOCKET; |
1104 | case NETLINK_DNRTMSG: | 1104 | case NETLINK_DNRTMSG: |
1105 | return SECCLASS_NETLINK_DNRT_SOCKET; | 1105 | return SECCLASS_NETLINK_DNRT_SOCKET; |
1106 | case NETLINK_KOBJECT_UEVENT: | 1106 | case NETLINK_KOBJECT_UEVENT: |
1107 | return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET; | 1107 | return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET; |
1108 | default: | 1108 | default: |
1109 | return SECCLASS_NETLINK_SOCKET; | 1109 | return SECCLASS_NETLINK_SOCKET; |
1110 | } | 1110 | } |
1111 | case PF_PACKET: | 1111 | case PF_PACKET: |
1112 | return SECCLASS_PACKET_SOCKET; | 1112 | return SECCLASS_PACKET_SOCKET; |
1113 | case PF_KEY: | 1113 | case PF_KEY: |
1114 | return SECCLASS_KEY_SOCKET; | 1114 | return SECCLASS_KEY_SOCKET; |
1115 | case PF_APPLETALK: | 1115 | case PF_APPLETALK: |
1116 | return SECCLASS_APPLETALK_SOCKET; | 1116 | return SECCLASS_APPLETALK_SOCKET; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | return SECCLASS_SOCKET; | 1119 | return SECCLASS_SOCKET; |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | #ifdef CONFIG_PROC_FS | 1122 | #ifdef CONFIG_PROC_FS |
1123 | static int selinux_proc_get_sid(struct dentry *dentry, | 1123 | static int selinux_proc_get_sid(struct dentry *dentry, |
1124 | u16 tclass, | 1124 | u16 tclass, |
1125 | u32 *sid) | 1125 | u32 *sid) |
1126 | { | 1126 | { |
1127 | int rc; | 1127 | int rc; |
1128 | char *buffer, *path; | 1128 | char *buffer, *path; |
1129 | 1129 | ||
1130 | buffer = (char *)__get_free_page(GFP_KERNEL); | 1130 | buffer = (char *)__get_free_page(GFP_KERNEL); |
1131 | if (!buffer) | 1131 | if (!buffer) |
1132 | return -ENOMEM; | 1132 | return -ENOMEM; |
1133 | 1133 | ||
1134 | path = dentry_path_raw(dentry, buffer, PAGE_SIZE); | 1134 | path = dentry_path_raw(dentry, buffer, PAGE_SIZE); |
1135 | if (IS_ERR(path)) | 1135 | if (IS_ERR(path)) |
1136 | rc = PTR_ERR(path); | 1136 | rc = PTR_ERR(path); |
1137 | else { | 1137 | else { |
1138 | /* each process gets a /proc/PID/ entry. Strip off the | 1138 | /* each process gets a /proc/PID/ entry. Strip off the |
1139 | * PID part to get a valid selinux labeling. | 1139 | * PID part to get a valid selinux labeling. |
1140 | * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ | 1140 | * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ |
1141 | while (path[1] >= '0' && path[1] <= '9') { | 1141 | while (path[1] >= '0' && path[1] <= '9') { |
1142 | path[1] = '/'; | 1142 | path[1] = '/'; |
1143 | path++; | 1143 | path++; |
1144 | } | 1144 | } |
1145 | rc = security_genfs_sid("proc", path, tclass, sid); | 1145 | rc = security_genfs_sid("proc", path, tclass, sid); |
1146 | } | 1146 | } |
1147 | free_page((unsigned long)buffer); | 1147 | free_page((unsigned long)buffer); |
1148 | return rc; | 1148 | return rc; |
1149 | } | 1149 | } |
1150 | #else | 1150 | #else |
1151 | static int selinux_proc_get_sid(struct dentry *dentry, | 1151 | static int selinux_proc_get_sid(struct dentry *dentry, |
1152 | u16 tclass, | 1152 | u16 tclass, |
1153 | u32 *sid) | 1153 | u32 *sid) |
1154 | { | 1154 | { |
1155 | return -EINVAL; | 1155 | return -EINVAL; |
1156 | } | 1156 | } |
1157 | #endif | 1157 | #endif |
1158 | 1158 | ||
1159 | /* The inode's security attributes must be initialized before first use. */ | 1159 | /* The inode's security attributes must be initialized before first use. */ |
1160 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) | 1160 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) |
1161 | { | 1161 | { |
1162 | struct superblock_security_struct *sbsec = NULL; | 1162 | struct superblock_security_struct *sbsec = NULL; |
1163 | struct inode_security_struct *isec = inode->i_security; | 1163 | struct inode_security_struct *isec = inode->i_security; |
1164 | u32 sid; | 1164 | u32 sid; |
1165 | struct dentry *dentry; | 1165 | struct dentry *dentry; |
1166 | #define INITCONTEXTLEN 255 | 1166 | #define INITCONTEXTLEN 255 |
1167 | char *context = NULL; | 1167 | char *context = NULL; |
1168 | unsigned len = 0; | 1168 | unsigned len = 0; |
1169 | int rc = 0; | 1169 | int rc = 0; |
1170 | 1170 | ||
1171 | if (isec->initialized) | 1171 | if (isec->initialized) |
1172 | goto out; | 1172 | goto out; |
1173 | 1173 | ||
1174 | mutex_lock(&isec->lock); | 1174 | mutex_lock(&isec->lock); |
1175 | if (isec->initialized) | 1175 | if (isec->initialized) |
1176 | goto out_unlock; | 1176 | goto out_unlock; |
1177 | 1177 | ||
1178 | sbsec = inode->i_sb->s_security; | 1178 | sbsec = inode->i_sb->s_security; |
1179 | if (!(sbsec->flags & SE_SBINITIALIZED)) { | 1179 | if (!(sbsec->flags & SE_SBINITIALIZED)) { |
1180 | /* Defer initialization until selinux_complete_init, | 1180 | /* Defer initialization until selinux_complete_init, |
1181 | after the initial policy is loaded and the security | 1181 | after the initial policy is loaded and the security |
1182 | server is ready to handle calls. */ | 1182 | server is ready to handle calls. */ |
1183 | spin_lock(&sbsec->isec_lock); | 1183 | spin_lock(&sbsec->isec_lock); |
1184 | if (list_empty(&isec->list)) | 1184 | if (list_empty(&isec->list)) |
1185 | list_add(&isec->list, &sbsec->isec_head); | 1185 | list_add(&isec->list, &sbsec->isec_head); |
1186 | spin_unlock(&sbsec->isec_lock); | 1186 | spin_unlock(&sbsec->isec_lock); |
1187 | goto out_unlock; | 1187 | goto out_unlock; |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | switch (sbsec->behavior) { | 1190 | switch (sbsec->behavior) { |
1191 | case SECURITY_FS_USE_XATTR: | 1191 | case SECURITY_FS_USE_XATTR: |
1192 | if (!inode->i_op->getxattr) { | 1192 | if (!inode->i_op->getxattr) { |
1193 | isec->sid = sbsec->def_sid; | 1193 | isec->sid = sbsec->def_sid; |
1194 | break; | 1194 | break; |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | /* Need a dentry, since the xattr API requires one. | 1197 | /* Need a dentry, since the xattr API requires one. |
1198 | Life would be simpler if we could just pass the inode. */ | 1198 | Life would be simpler if we could just pass the inode. */ |
1199 | if (opt_dentry) { | 1199 | if (opt_dentry) { |
1200 | /* Called from d_instantiate or d_splice_alias. */ | 1200 | /* Called from d_instantiate or d_splice_alias. */ |
1201 | dentry = dget(opt_dentry); | 1201 | dentry = dget(opt_dentry); |
1202 | } else { | 1202 | } else { |
1203 | /* Called from selinux_complete_init, try to find a dentry. */ | 1203 | /* Called from selinux_complete_init, try to find a dentry. */ |
1204 | dentry = d_find_alias(inode); | 1204 | dentry = d_find_alias(inode); |
1205 | } | 1205 | } |
1206 | if (!dentry) { | 1206 | if (!dentry) { |
1207 | /* | 1207 | /* |
1208 | * this is can be hit on boot when a file is accessed | 1208 | * this is can be hit on boot when a file is accessed |
1209 | * before the policy is loaded. When we load policy we | 1209 | * before the policy is loaded. When we load policy we |
1210 | * may find inodes that have no dentry on the | 1210 | * may find inodes that have no dentry on the |
1211 | * sbsec->isec_head list. No reason to complain as these | 1211 | * sbsec->isec_head list. No reason to complain as these |
1212 | * will get fixed up the next time we go through | 1212 | * will get fixed up the next time we go through |
1213 | * inode_doinit with a dentry, before these inodes could | 1213 | * inode_doinit with a dentry, before these inodes could |
1214 | * be used again by userspace. | 1214 | * be used again by userspace. |
1215 | */ | 1215 | */ |
1216 | goto out_unlock; | 1216 | goto out_unlock; |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | len = INITCONTEXTLEN; | 1219 | len = INITCONTEXTLEN; |
1220 | context = kmalloc(len+1, GFP_NOFS); | 1220 | context = kmalloc(len+1, GFP_NOFS); |
1221 | if (!context) { | 1221 | if (!context) { |
1222 | rc = -ENOMEM; | 1222 | rc = -ENOMEM; |
1223 | dput(dentry); | 1223 | dput(dentry); |
1224 | goto out_unlock; | 1224 | goto out_unlock; |
1225 | } | 1225 | } |
1226 | context[len] = '\0'; | 1226 | context[len] = '\0'; |
1227 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, | 1227 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, |
1228 | context, len); | 1228 | context, len); |
1229 | if (rc == -ERANGE) { | 1229 | if (rc == -ERANGE) { |
1230 | kfree(context); | 1230 | kfree(context); |
1231 | 1231 | ||
1232 | /* Need a larger buffer. Query for the right size. */ | 1232 | /* Need a larger buffer. Query for the right size. */ |
1233 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, | 1233 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, |
1234 | NULL, 0); | 1234 | NULL, 0); |
1235 | if (rc < 0) { | 1235 | if (rc < 0) { |
1236 | dput(dentry); | 1236 | dput(dentry); |
1237 | goto out_unlock; | 1237 | goto out_unlock; |
1238 | } | 1238 | } |
1239 | len = rc; | 1239 | len = rc; |
1240 | context = kmalloc(len+1, GFP_NOFS); | 1240 | context = kmalloc(len+1, GFP_NOFS); |
1241 | if (!context) { | 1241 | if (!context) { |
1242 | rc = -ENOMEM; | 1242 | rc = -ENOMEM; |
1243 | dput(dentry); | 1243 | dput(dentry); |
1244 | goto out_unlock; | 1244 | goto out_unlock; |
1245 | } | 1245 | } |
1246 | context[len] = '\0'; | 1246 | context[len] = '\0'; |
1247 | rc = inode->i_op->getxattr(dentry, | 1247 | rc = inode->i_op->getxattr(dentry, |
1248 | XATTR_NAME_SELINUX, | 1248 | XATTR_NAME_SELINUX, |
1249 | context, len); | 1249 | context, len); |
1250 | } | 1250 | } |
1251 | dput(dentry); | 1251 | dput(dentry); |
1252 | if (rc < 0) { | 1252 | if (rc < 0) { |
1253 | if (rc != -ENODATA) { | 1253 | if (rc != -ENODATA) { |
1254 | printk(KERN_WARNING "SELinux: %s: getxattr returned " | 1254 | printk(KERN_WARNING "SELinux: %s: getxattr returned " |
1255 | "%d for dev=%s ino=%ld\n", __func__, | 1255 | "%d for dev=%s ino=%ld\n", __func__, |
1256 | -rc, inode->i_sb->s_id, inode->i_ino); | 1256 | -rc, inode->i_sb->s_id, inode->i_ino); |
1257 | kfree(context); | 1257 | kfree(context); |
1258 | goto out_unlock; | 1258 | goto out_unlock; |
1259 | } | 1259 | } |
1260 | /* Map ENODATA to the default file SID */ | 1260 | /* Map ENODATA to the default file SID */ |
1261 | sid = sbsec->def_sid; | 1261 | sid = sbsec->def_sid; |
1262 | rc = 0; | 1262 | rc = 0; |
1263 | } else { | 1263 | } else { |
1264 | rc = security_context_to_sid_default(context, rc, &sid, | 1264 | rc = security_context_to_sid_default(context, rc, &sid, |
1265 | sbsec->def_sid, | 1265 | sbsec->def_sid, |
1266 | GFP_NOFS); | 1266 | GFP_NOFS); |
1267 | if (rc) { | 1267 | if (rc) { |
1268 | char *dev = inode->i_sb->s_id; | 1268 | char *dev = inode->i_sb->s_id; |
1269 | unsigned long ino = inode->i_ino; | 1269 | unsigned long ino = inode->i_ino; |
1270 | 1270 | ||
1271 | if (rc == -EINVAL) { | 1271 | if (rc == -EINVAL) { |
1272 | if (printk_ratelimit()) | 1272 | if (printk_ratelimit()) |
1273 | printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid " | 1273 | printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid " |
1274 | "context=%s. This indicates you may need to relabel the inode or the " | 1274 | "context=%s. This indicates you may need to relabel the inode or the " |
1275 | "filesystem in question.\n", ino, dev, context); | 1275 | "filesystem in question.\n", ino, dev, context); |
1276 | } else { | 1276 | } else { |
1277 | printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) " | 1277 | printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) " |
1278 | "returned %d for dev=%s ino=%ld\n", | 1278 | "returned %d for dev=%s ino=%ld\n", |
1279 | __func__, context, -rc, dev, ino); | 1279 | __func__, context, -rc, dev, ino); |
1280 | } | 1280 | } |
1281 | kfree(context); | 1281 | kfree(context); |
1282 | /* Leave with the unlabeled SID */ | 1282 | /* Leave with the unlabeled SID */ |
1283 | rc = 0; | 1283 | rc = 0; |
1284 | break; | 1284 | break; |
1285 | } | 1285 | } |
1286 | } | 1286 | } |
1287 | kfree(context); | 1287 | kfree(context); |
1288 | isec->sid = sid; | 1288 | isec->sid = sid; |
1289 | break; | 1289 | break; |
1290 | case SECURITY_FS_USE_TASK: | 1290 | case SECURITY_FS_USE_TASK: |
1291 | isec->sid = isec->task_sid; | 1291 | isec->sid = isec->task_sid; |
1292 | break; | 1292 | break; |
1293 | case SECURITY_FS_USE_TRANS: | 1293 | case SECURITY_FS_USE_TRANS: |
1294 | /* Default to the fs SID. */ | 1294 | /* Default to the fs SID. */ |
1295 | isec->sid = sbsec->sid; | 1295 | isec->sid = sbsec->sid; |
1296 | 1296 | ||
1297 | /* Try to obtain a transition SID. */ | 1297 | /* Try to obtain a transition SID. */ |
1298 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1298 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
1299 | rc = security_transition_sid(isec->task_sid, sbsec->sid, | 1299 | rc = security_transition_sid(isec->task_sid, sbsec->sid, |
1300 | isec->sclass, NULL, &sid); | 1300 | isec->sclass, NULL, &sid); |
1301 | if (rc) | 1301 | if (rc) |
1302 | goto out_unlock; | 1302 | goto out_unlock; |
1303 | isec->sid = sid; | 1303 | isec->sid = sid; |
1304 | break; | 1304 | break; |
1305 | case SECURITY_FS_USE_MNTPOINT: | 1305 | case SECURITY_FS_USE_MNTPOINT: |
1306 | isec->sid = sbsec->mntpoint_sid; | 1306 | isec->sid = sbsec->mntpoint_sid; |
1307 | break; | 1307 | break; |
1308 | default: | 1308 | default: |
1309 | /* Default to the fs superblock SID. */ | 1309 | /* Default to the fs superblock SID. */ |
1310 | isec->sid = sbsec->sid; | 1310 | isec->sid = sbsec->sid; |
1311 | 1311 | ||
1312 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { | 1312 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { |
1313 | if (opt_dentry) { | 1313 | if (opt_dentry) { |
1314 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1314 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
1315 | rc = selinux_proc_get_sid(opt_dentry, | 1315 | rc = selinux_proc_get_sid(opt_dentry, |
1316 | isec->sclass, | 1316 | isec->sclass, |
1317 | &sid); | 1317 | &sid); |
1318 | if (rc) | 1318 | if (rc) |
1319 | goto out_unlock; | 1319 | goto out_unlock; |
1320 | isec->sid = sid; | 1320 | isec->sid = sid; |
1321 | } | 1321 | } |
1322 | } | 1322 | } |
1323 | break; | 1323 | break; |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | isec->initialized = 1; | 1326 | isec->initialized = 1; |
1327 | 1327 | ||
1328 | out_unlock: | 1328 | out_unlock: |
1329 | mutex_unlock(&isec->lock); | 1329 | mutex_unlock(&isec->lock); |
1330 | out: | 1330 | out: |
1331 | if (isec->sclass == SECCLASS_FILE) | 1331 | if (isec->sclass == SECCLASS_FILE) |
1332 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1332 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
1333 | return rc; | 1333 | return rc; |
1334 | } | 1334 | } |
1335 | 1335 | ||
1336 | /* Convert a Linux signal to an access vector. */ | 1336 | /* Convert a Linux signal to an access vector. */ |
1337 | static inline u32 signal_to_av(int sig) | 1337 | static inline u32 signal_to_av(int sig) |
1338 | { | 1338 | { |
1339 | u32 perm = 0; | 1339 | u32 perm = 0; |
1340 | 1340 | ||
1341 | switch (sig) { | 1341 | switch (sig) { |
1342 | case SIGCHLD: | 1342 | case SIGCHLD: |
1343 | /* Commonly granted from child to parent. */ | 1343 | /* Commonly granted from child to parent. */ |
1344 | perm = PROCESS__SIGCHLD; | 1344 | perm = PROCESS__SIGCHLD; |
1345 | break; | 1345 | break; |
1346 | case SIGKILL: | 1346 | case SIGKILL: |
1347 | /* Cannot be caught or ignored */ | 1347 | /* Cannot be caught or ignored */ |
1348 | perm = PROCESS__SIGKILL; | 1348 | perm = PROCESS__SIGKILL; |
1349 | break; | 1349 | break; |
1350 | case SIGSTOP: | 1350 | case SIGSTOP: |
1351 | /* Cannot be caught or ignored */ | 1351 | /* Cannot be caught or ignored */ |
1352 | perm = PROCESS__SIGSTOP; | 1352 | perm = PROCESS__SIGSTOP; |
1353 | break; | 1353 | break; |
1354 | default: | 1354 | default: |
1355 | /* All other signals. */ | 1355 | /* All other signals. */ |
1356 | perm = PROCESS__SIGNAL; | 1356 | perm = PROCESS__SIGNAL; |
1357 | break; | 1357 | break; |
1358 | } | 1358 | } |
1359 | 1359 | ||
1360 | return perm; | 1360 | return perm; |
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | /* | 1363 | /* |
1364 | * Check permission between a pair of credentials | 1364 | * Check permission between a pair of credentials |
1365 | * fork check, ptrace check, etc. | 1365 | * fork check, ptrace check, etc. |
1366 | */ | 1366 | */ |
1367 | static int cred_has_perm(const struct cred *actor, | 1367 | static int cred_has_perm(const struct cred *actor, |
1368 | const struct cred *target, | 1368 | const struct cred *target, |
1369 | u32 perms) | 1369 | u32 perms) |
1370 | { | 1370 | { |
1371 | u32 asid = cred_sid(actor), tsid = cred_sid(target); | 1371 | u32 asid = cred_sid(actor), tsid = cred_sid(target); |
1372 | 1372 | ||
1373 | return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL); | 1373 | return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL); |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | /* | 1376 | /* |
1377 | * Check permission between a pair of tasks, e.g. signal checks, | 1377 | * Check permission between a pair of tasks, e.g. signal checks, |
1378 | * fork check, ptrace check, etc. | 1378 | * fork check, ptrace check, etc. |
1379 | * tsk1 is the actor and tsk2 is the target | 1379 | * tsk1 is the actor and tsk2 is the target |
1380 | * - this uses the default subjective creds of tsk1 | 1380 | * - this uses the default subjective creds of tsk1 |
1381 | */ | 1381 | */ |
1382 | static int task_has_perm(const struct task_struct *tsk1, | 1382 | static int task_has_perm(const struct task_struct *tsk1, |
1383 | const struct task_struct *tsk2, | 1383 | const struct task_struct *tsk2, |
1384 | u32 perms) | 1384 | u32 perms) |
1385 | { | 1385 | { |
1386 | const struct task_security_struct *__tsec1, *__tsec2; | 1386 | const struct task_security_struct *__tsec1, *__tsec2; |
1387 | u32 sid1, sid2; | 1387 | u32 sid1, sid2; |
1388 | 1388 | ||
1389 | rcu_read_lock(); | 1389 | rcu_read_lock(); |
1390 | __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid; | 1390 | __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid; |
1391 | __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid; | 1391 | __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid; |
1392 | rcu_read_unlock(); | 1392 | rcu_read_unlock(); |
1393 | return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL); | 1393 | return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | /* | 1396 | /* |
1397 | * Check permission between current and another task, e.g. signal checks, | 1397 | * Check permission between current and another task, e.g. signal checks, |
1398 | * fork check, ptrace check, etc. | 1398 | * fork check, ptrace check, etc. |
1399 | * current is the actor and tsk2 is the target | 1399 | * current is the actor and tsk2 is the target |
1400 | * - this uses current's subjective creds | 1400 | * - this uses current's subjective creds |
1401 | */ | 1401 | */ |
1402 | static int current_has_perm(const struct task_struct *tsk, | 1402 | static int current_has_perm(const struct task_struct *tsk, |
1403 | u32 perms) | 1403 | u32 perms) |
1404 | { | 1404 | { |
1405 | u32 sid, tsid; | 1405 | u32 sid, tsid; |
1406 | 1406 | ||
1407 | sid = current_sid(); | 1407 | sid = current_sid(); |
1408 | tsid = task_sid(tsk); | 1408 | tsid = task_sid(tsk); |
1409 | return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL); | 1409 | return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL); |
1410 | } | 1410 | } |
1411 | 1411 | ||
1412 | #if CAP_LAST_CAP > 63 | 1412 | #if CAP_LAST_CAP > 63 |
1413 | #error Fix SELinux to handle capabilities > 63. | 1413 | #error Fix SELinux to handle capabilities > 63. |
1414 | #endif | 1414 | #endif |
1415 | 1415 | ||
1416 | /* Check whether a task is allowed to use a capability. */ | 1416 | /* Check whether a task is allowed to use a capability. */ |
1417 | static int cred_has_capability(const struct cred *cred, | 1417 | static int cred_has_capability(const struct cred *cred, |
1418 | int cap, int audit) | 1418 | int cap, int audit) |
1419 | { | 1419 | { |
1420 | struct common_audit_data ad; | 1420 | struct common_audit_data ad; |
1421 | struct av_decision avd; | 1421 | struct av_decision avd; |
1422 | u16 sclass; | 1422 | u16 sclass; |
1423 | u32 sid = cred_sid(cred); | 1423 | u32 sid = cred_sid(cred); |
1424 | u32 av = CAP_TO_MASK(cap); | 1424 | u32 av = CAP_TO_MASK(cap); |
1425 | int rc; | 1425 | int rc; |
1426 | 1426 | ||
1427 | COMMON_AUDIT_DATA_INIT(&ad, CAP); | 1427 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1428 | ad.tsk = current; | 1428 | ad.tsk = current; |
1429 | ad.u.cap = cap; | 1429 | ad.u.cap = cap; |
1430 | 1430 | ||
1431 | switch (CAP_TO_INDEX(cap)) { | 1431 | switch (CAP_TO_INDEX(cap)) { |
1432 | case 0: | 1432 | case 0: |
1433 | sclass = SECCLASS_CAPABILITY; | 1433 | sclass = SECCLASS_CAPABILITY; |
1434 | break; | 1434 | break; |
1435 | case 1: | 1435 | case 1: |
1436 | sclass = SECCLASS_CAPABILITY2; | 1436 | sclass = SECCLASS_CAPABILITY2; |
1437 | break; | 1437 | break; |
1438 | default: | 1438 | default: |
1439 | printk(KERN_ERR | 1439 | printk(KERN_ERR |
1440 | "SELinux: out of range capability %d\n", cap); | 1440 | "SELinux: out of range capability %d\n", cap); |
1441 | BUG(); | 1441 | BUG(); |
1442 | return -EINVAL; | 1442 | return -EINVAL; |
1443 | } | 1443 | } |
1444 | 1444 | ||
1445 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | 1445 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); |
1446 | if (audit == SECURITY_CAP_AUDIT) { | 1446 | if (audit == SECURITY_CAP_AUDIT) { |
1447 | int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); | 1447 | int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); |
1448 | if (rc2) | 1448 | if (rc2) |
1449 | return rc2; | 1449 | return rc2; |
1450 | } | 1450 | } |
1451 | return rc; | 1451 | return rc; |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | /* Check whether a task is allowed to use a system operation. */ | 1454 | /* Check whether a task is allowed to use a system operation. */ |
1455 | static int task_has_system(struct task_struct *tsk, | 1455 | static int task_has_system(struct task_struct *tsk, |
1456 | u32 perms) | 1456 | u32 perms) |
1457 | { | 1457 | { |
1458 | u32 sid = task_sid(tsk); | 1458 | u32 sid = task_sid(tsk); |
1459 | 1459 | ||
1460 | return avc_has_perm(sid, SECINITSID_KERNEL, | 1460 | return avc_has_perm(sid, SECINITSID_KERNEL, |
1461 | SECCLASS_SYSTEM, perms, NULL); | 1461 | SECCLASS_SYSTEM, perms, NULL); |
1462 | } | 1462 | } |
1463 | 1463 | ||
1464 | /* Check whether a task has a particular permission to an inode. | 1464 | /* Check whether a task has a particular permission to an inode. |
1465 | The 'adp' parameter is optional and allows other audit | 1465 | The 'adp' parameter is optional and allows other audit |
1466 | data to be passed (e.g. the dentry). */ | 1466 | data to be passed (e.g. the dentry). */ |
1467 | static int inode_has_perm(const struct cred *cred, | 1467 | static int inode_has_perm(const struct cred *cred, |
1468 | struct inode *inode, | 1468 | struct inode *inode, |
1469 | u32 perms, | 1469 | u32 perms, |
1470 | struct common_audit_data *adp, | 1470 | struct common_audit_data *adp, |
1471 | unsigned flags) | 1471 | unsigned flags) |
1472 | { | 1472 | { |
1473 | struct inode_security_struct *isec; | 1473 | struct inode_security_struct *isec; |
1474 | u32 sid; | 1474 | u32 sid; |
1475 | 1475 | ||
1476 | validate_creds(cred); | 1476 | validate_creds(cred); |
1477 | 1477 | ||
1478 | if (unlikely(IS_PRIVATE(inode))) | 1478 | if (unlikely(IS_PRIVATE(inode))) |
1479 | return 0; | 1479 | return 0; |
1480 | 1480 | ||
1481 | sid = cred_sid(cred); | 1481 | sid = cred_sid(cred); |
1482 | isec = inode->i_security; | 1482 | isec = inode->i_security; |
1483 | 1483 | ||
1484 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1484 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); |
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | static int inode_has_perm_noadp(const struct cred *cred, | 1487 | static int inode_has_perm_noadp(const struct cred *cred, |
1488 | struct inode *inode, | 1488 | struct inode *inode, |
1489 | u32 perms, | 1489 | u32 perms, |
1490 | unsigned flags) | 1490 | unsigned flags) |
1491 | { | 1491 | { |
1492 | struct common_audit_data ad; | 1492 | struct common_audit_data ad; |
1493 | 1493 | ||
1494 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | 1494 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
1495 | ad.u.inode = inode; | 1495 | ad.u.inode = inode; |
1496 | return inode_has_perm(cred, inode, perms, &ad, flags); | 1496 | return inode_has_perm(cred, inode, perms, &ad, flags); |
1497 | } | 1497 | } |
1498 | 1498 | ||
1499 | /* Same as inode_has_perm, but pass explicit audit data containing | 1499 | /* Same as inode_has_perm, but pass explicit audit data containing |
1500 | the dentry to help the auditing code to more easily generate the | 1500 | the dentry to help the auditing code to more easily generate the |
1501 | pathname if needed. */ | 1501 | pathname if needed. */ |
1502 | static inline int dentry_has_perm(const struct cred *cred, | 1502 | static inline int dentry_has_perm(const struct cred *cred, |
1503 | struct dentry *dentry, | 1503 | struct dentry *dentry, |
1504 | u32 av) | 1504 | u32 av) |
1505 | { | 1505 | { |
1506 | struct inode *inode = dentry->d_inode; | 1506 | struct inode *inode = dentry->d_inode; |
1507 | struct common_audit_data ad; | 1507 | struct common_audit_data ad; |
1508 | 1508 | ||
1509 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1509 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1510 | ad.u.dentry = dentry; | 1510 | ad.u.dentry = dentry; |
1511 | return inode_has_perm(cred, inode, av, &ad, 0); | 1511 | return inode_has_perm(cred, inode, av, &ad, 0); |
1512 | } | 1512 | } |
1513 | 1513 | ||
1514 | /* Same as inode_has_perm, but pass explicit audit data containing | 1514 | /* Same as inode_has_perm, but pass explicit audit data containing |
1515 | the path to help the auditing code to more easily generate the | 1515 | the path to help the auditing code to more easily generate the |
1516 | pathname if needed. */ | 1516 | pathname if needed. */ |
1517 | static inline int path_has_perm(const struct cred *cred, | 1517 | static inline int path_has_perm(const struct cred *cred, |
1518 | struct path *path, | 1518 | struct path *path, |
1519 | u32 av) | 1519 | u32 av) |
1520 | { | 1520 | { |
1521 | struct inode *inode = path->dentry->d_inode; | 1521 | struct inode *inode = path->dentry->d_inode; |
1522 | struct common_audit_data ad; | 1522 | struct common_audit_data ad; |
1523 | 1523 | ||
1524 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1524 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1525 | ad.u.path = *path; | 1525 | ad.u.path = *path; |
1526 | return inode_has_perm(cred, inode, av, &ad, 0); | 1526 | return inode_has_perm(cred, inode, av, &ad, 0); |
1527 | } | 1527 | } |
1528 | 1528 | ||
1529 | /* Check whether a task can use an open file descriptor to | 1529 | /* Check whether a task can use an open file descriptor to |
1530 | access an inode in a given way. Check access to the | 1530 | access an inode in a given way. Check access to the |
1531 | descriptor itself, and then use dentry_has_perm to | 1531 | descriptor itself, and then use dentry_has_perm to |
1532 | check a particular permission to the file. | 1532 | check a particular permission to the file. |
1533 | Access to the descriptor is implicitly granted if it | 1533 | Access to the descriptor is implicitly granted if it |
1534 | has the same SID as the process. If av is zero, then | 1534 | has the same SID as the process. If av is zero, then |
1535 | access to the file is not checked, e.g. for cases | 1535 | access to the file is not checked, e.g. for cases |
1536 | where only the descriptor is affected like seek. */ | 1536 | where only the descriptor is affected like seek. */ |
1537 | static int file_has_perm(const struct cred *cred, | 1537 | static int file_has_perm(const struct cred *cred, |
1538 | struct file *file, | 1538 | struct file *file, |
1539 | u32 av) | 1539 | u32 av) |
1540 | { | 1540 | { |
1541 | struct file_security_struct *fsec = file->f_security; | 1541 | struct file_security_struct *fsec = file->f_security; |
1542 | struct inode *inode = file->f_path.dentry->d_inode; | 1542 | struct inode *inode = file->f_path.dentry->d_inode; |
1543 | struct common_audit_data ad; | 1543 | struct common_audit_data ad; |
1544 | u32 sid = cred_sid(cred); | 1544 | u32 sid = cred_sid(cred); |
1545 | int rc; | 1545 | int rc; |
1546 | 1546 | ||
1547 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1547 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1548 | ad.u.path = file->f_path; | 1548 | ad.u.path = file->f_path; |
1549 | 1549 | ||
1550 | if (sid != fsec->sid) { | 1550 | if (sid != fsec->sid) { |
1551 | rc = avc_has_perm(sid, fsec->sid, | 1551 | rc = avc_has_perm(sid, fsec->sid, |
1552 | SECCLASS_FD, | 1552 | SECCLASS_FD, |
1553 | FD__USE, | 1553 | FD__USE, |
1554 | &ad); | 1554 | &ad); |
1555 | if (rc) | 1555 | if (rc) |
1556 | goto out; | 1556 | goto out; |
1557 | } | 1557 | } |
1558 | 1558 | ||
1559 | /* av is zero if only checking access to the descriptor. */ | 1559 | /* av is zero if only checking access to the descriptor. */ |
1560 | rc = 0; | 1560 | rc = 0; |
1561 | if (av) | 1561 | if (av) |
1562 | rc = inode_has_perm(cred, inode, av, &ad, 0); | 1562 | rc = inode_has_perm(cred, inode, av, &ad, 0); |
1563 | 1563 | ||
1564 | out: | 1564 | out: |
1565 | return rc; | 1565 | return rc; |
1566 | } | 1566 | } |
1567 | 1567 | ||
1568 | /* Check whether a task can create a file. */ | 1568 | /* Check whether a task can create a file. */ |
1569 | static int may_create(struct inode *dir, | 1569 | static int may_create(struct inode *dir, |
1570 | struct dentry *dentry, | 1570 | struct dentry *dentry, |
1571 | u16 tclass) | 1571 | u16 tclass) |
1572 | { | 1572 | { |
1573 | const struct task_security_struct *tsec = current_security(); | 1573 | const struct task_security_struct *tsec = current_security(); |
1574 | struct inode_security_struct *dsec; | 1574 | struct inode_security_struct *dsec; |
1575 | struct superblock_security_struct *sbsec; | 1575 | struct superblock_security_struct *sbsec; |
1576 | u32 sid, newsid; | 1576 | u32 sid, newsid; |
1577 | struct common_audit_data ad; | 1577 | struct common_audit_data ad; |
1578 | int rc; | 1578 | int rc; |
1579 | 1579 | ||
1580 | dsec = dir->i_security; | 1580 | dsec = dir->i_security; |
1581 | sbsec = dir->i_sb->s_security; | 1581 | sbsec = dir->i_sb->s_security; |
1582 | 1582 | ||
1583 | sid = tsec->sid; | 1583 | sid = tsec->sid; |
1584 | newsid = tsec->create_sid; | 1584 | newsid = tsec->create_sid; |
1585 | 1585 | ||
1586 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1586 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1587 | ad.u.dentry = dentry; | 1587 | ad.u.dentry = dentry; |
1588 | 1588 | ||
1589 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1589 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
1590 | DIR__ADD_NAME | DIR__SEARCH, | 1590 | DIR__ADD_NAME | DIR__SEARCH, |
1591 | &ad); | 1591 | &ad); |
1592 | if (rc) | 1592 | if (rc) |
1593 | return rc; | 1593 | return rc; |
1594 | 1594 | ||
1595 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 1595 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { |
1596 | rc = security_transition_sid(sid, dsec->sid, tclass, | 1596 | rc = security_transition_sid(sid, dsec->sid, tclass, |
1597 | &dentry->d_name, &newsid); | 1597 | &dentry->d_name, &newsid); |
1598 | if (rc) | 1598 | if (rc) |
1599 | return rc; | 1599 | return rc; |
1600 | } | 1600 | } |
1601 | 1601 | ||
1602 | rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); | 1602 | rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); |
1603 | if (rc) | 1603 | if (rc) |
1604 | return rc; | 1604 | return rc; |
1605 | 1605 | ||
1606 | return avc_has_perm(newsid, sbsec->sid, | 1606 | return avc_has_perm(newsid, sbsec->sid, |
1607 | SECCLASS_FILESYSTEM, | 1607 | SECCLASS_FILESYSTEM, |
1608 | FILESYSTEM__ASSOCIATE, &ad); | 1608 | FILESYSTEM__ASSOCIATE, &ad); |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | /* Check whether a task can create a key. */ | 1611 | /* Check whether a task can create a key. */ |
1612 | static int may_create_key(u32 ksid, | 1612 | static int may_create_key(u32 ksid, |
1613 | struct task_struct *ctx) | 1613 | struct task_struct *ctx) |
1614 | { | 1614 | { |
1615 | u32 sid = task_sid(ctx); | 1615 | u32 sid = task_sid(ctx); |
1616 | 1616 | ||
1617 | return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); | 1617 | return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); |
1618 | } | 1618 | } |
1619 | 1619 | ||
1620 | #define MAY_LINK 0 | 1620 | #define MAY_LINK 0 |
1621 | #define MAY_UNLINK 1 | 1621 | #define MAY_UNLINK 1 |
1622 | #define MAY_RMDIR 2 | 1622 | #define MAY_RMDIR 2 |
1623 | 1623 | ||
1624 | /* Check whether a task can link, unlink, or rmdir a file/directory. */ | 1624 | /* Check whether a task can link, unlink, or rmdir a file/directory. */ |
1625 | static int may_link(struct inode *dir, | 1625 | static int may_link(struct inode *dir, |
1626 | struct dentry *dentry, | 1626 | struct dentry *dentry, |
1627 | int kind) | 1627 | int kind) |
1628 | 1628 | ||
1629 | { | 1629 | { |
1630 | struct inode_security_struct *dsec, *isec; | 1630 | struct inode_security_struct *dsec, *isec; |
1631 | struct common_audit_data ad; | 1631 | struct common_audit_data ad; |
1632 | u32 sid = current_sid(); | 1632 | u32 sid = current_sid(); |
1633 | u32 av; | 1633 | u32 av; |
1634 | int rc; | 1634 | int rc; |
1635 | 1635 | ||
1636 | dsec = dir->i_security; | 1636 | dsec = dir->i_security; |
1637 | isec = dentry->d_inode->i_security; | 1637 | isec = dentry->d_inode->i_security; |
1638 | 1638 | ||
1639 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1639 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1640 | ad.u.dentry = dentry; | 1640 | ad.u.dentry = dentry; |
1641 | 1641 | ||
1642 | av = DIR__SEARCH; | 1642 | av = DIR__SEARCH; |
1643 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 1643 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
1644 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad); | 1644 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad); |
1645 | if (rc) | 1645 | if (rc) |
1646 | return rc; | 1646 | return rc; |
1647 | 1647 | ||
1648 | switch (kind) { | 1648 | switch (kind) { |
1649 | case MAY_LINK: | 1649 | case MAY_LINK: |
1650 | av = FILE__LINK; | 1650 | av = FILE__LINK; |
1651 | break; | 1651 | break; |
1652 | case MAY_UNLINK: | 1652 | case MAY_UNLINK: |
1653 | av = FILE__UNLINK; | 1653 | av = FILE__UNLINK; |
1654 | break; | 1654 | break; |
1655 | case MAY_RMDIR: | 1655 | case MAY_RMDIR: |
1656 | av = DIR__RMDIR; | 1656 | av = DIR__RMDIR; |
1657 | break; | 1657 | break; |
1658 | default: | 1658 | default: |
1659 | printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n", | 1659 | printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n", |
1660 | __func__, kind); | 1660 | __func__, kind); |
1661 | return 0; | 1661 | return 0; |
1662 | } | 1662 | } |
1663 | 1663 | ||
1664 | rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); | 1664 | rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); |
1665 | return rc; | 1665 | return rc; |
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | static inline int may_rename(struct inode *old_dir, | 1668 | static inline int may_rename(struct inode *old_dir, |
1669 | struct dentry *old_dentry, | 1669 | struct dentry *old_dentry, |
1670 | struct inode *new_dir, | 1670 | struct inode *new_dir, |
1671 | struct dentry *new_dentry) | 1671 | struct dentry *new_dentry) |
1672 | { | 1672 | { |
1673 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1673 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1674 | struct common_audit_data ad; | 1674 | struct common_audit_data ad; |
1675 | u32 sid = current_sid(); | 1675 | u32 sid = current_sid(); |
1676 | u32 av; | 1676 | u32 av; |
1677 | int old_is_dir, new_is_dir; | 1677 | int old_is_dir, new_is_dir; |
1678 | int rc; | 1678 | int rc; |
1679 | 1679 | ||
1680 | old_dsec = old_dir->i_security; | 1680 | old_dsec = old_dir->i_security; |
1681 | old_isec = old_dentry->d_inode->i_security; | 1681 | old_isec = old_dentry->d_inode->i_security; |
1682 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1682 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1683 | new_dsec = new_dir->i_security; | 1683 | new_dsec = new_dir->i_security; |
1684 | 1684 | ||
1685 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1685 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1686 | 1686 | ||
1687 | ad.u.dentry = old_dentry; | 1687 | ad.u.dentry = old_dentry; |
1688 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1688 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
1689 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); | 1689 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); |
1690 | if (rc) | 1690 | if (rc) |
1691 | return rc; | 1691 | return rc; |
1692 | rc = avc_has_perm(sid, old_isec->sid, | 1692 | rc = avc_has_perm(sid, old_isec->sid, |
1693 | old_isec->sclass, FILE__RENAME, &ad); | 1693 | old_isec->sclass, FILE__RENAME, &ad); |
1694 | if (rc) | 1694 | if (rc) |
1695 | return rc; | 1695 | return rc; |
1696 | if (old_is_dir && new_dir != old_dir) { | 1696 | if (old_is_dir && new_dir != old_dir) { |
1697 | rc = avc_has_perm(sid, old_isec->sid, | 1697 | rc = avc_has_perm(sid, old_isec->sid, |
1698 | old_isec->sclass, DIR__REPARENT, &ad); | 1698 | old_isec->sclass, DIR__REPARENT, &ad); |
1699 | if (rc) | 1699 | if (rc) |
1700 | return rc; | 1700 | return rc; |
1701 | } | 1701 | } |
1702 | 1702 | ||
1703 | ad.u.dentry = new_dentry; | 1703 | ad.u.dentry = new_dentry; |
1704 | av = DIR__ADD_NAME | DIR__SEARCH; | 1704 | av = DIR__ADD_NAME | DIR__SEARCH; |
1705 | if (new_dentry->d_inode) | 1705 | if (new_dentry->d_inode) |
1706 | av |= DIR__REMOVE_NAME; | 1706 | av |= DIR__REMOVE_NAME; |
1707 | rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad); | 1707 | rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad); |
1708 | if (rc) | 1708 | if (rc) |
1709 | return rc; | 1709 | return rc; |
1710 | if (new_dentry->d_inode) { | 1710 | if (new_dentry->d_inode) { |
1711 | new_isec = new_dentry->d_inode->i_security; | 1711 | new_isec = new_dentry->d_inode->i_security; |
1712 | new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode); | 1712 | new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode); |
1713 | rc = avc_has_perm(sid, new_isec->sid, | 1713 | rc = avc_has_perm(sid, new_isec->sid, |
1714 | new_isec->sclass, | 1714 | new_isec->sclass, |
1715 | (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); | 1715 | (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); |
1716 | if (rc) | 1716 | if (rc) |
1717 | return rc; | 1717 | return rc; |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | return 0; | 1720 | return 0; |
1721 | } | 1721 | } |
1722 | 1722 | ||
1723 | /* Check whether a task can perform a filesystem operation. */ | 1723 | /* Check whether a task can perform a filesystem operation. */ |
1724 | static int superblock_has_perm(const struct cred *cred, | 1724 | static int superblock_has_perm(const struct cred *cred, |
1725 | struct super_block *sb, | 1725 | struct super_block *sb, |
1726 | u32 perms, | 1726 | u32 perms, |
1727 | struct common_audit_data *ad) | 1727 | struct common_audit_data *ad) |
1728 | { | 1728 | { |
1729 | struct superblock_security_struct *sbsec; | 1729 | struct superblock_security_struct *sbsec; |
1730 | u32 sid = cred_sid(cred); | 1730 | u32 sid = cred_sid(cred); |
1731 | 1731 | ||
1732 | sbsec = sb->s_security; | 1732 | sbsec = sb->s_security; |
1733 | return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); | 1733 | return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); |
1734 | } | 1734 | } |
1735 | 1735 | ||
1736 | /* Convert a Linux mode and permission mask to an access vector. */ | 1736 | /* Convert a Linux mode and permission mask to an access vector. */ |
1737 | static inline u32 file_mask_to_av(int mode, int mask) | 1737 | static inline u32 file_mask_to_av(int mode, int mask) |
1738 | { | 1738 | { |
1739 | u32 av = 0; | 1739 | u32 av = 0; |
1740 | 1740 | ||
1741 | if ((mode & S_IFMT) != S_IFDIR) { | 1741 | if ((mode & S_IFMT) != S_IFDIR) { |
1742 | if (mask & MAY_EXEC) | 1742 | if (mask & MAY_EXEC) |
1743 | av |= FILE__EXECUTE; | 1743 | av |= FILE__EXECUTE; |
1744 | if (mask & MAY_READ) | 1744 | if (mask & MAY_READ) |
1745 | av |= FILE__READ; | 1745 | av |= FILE__READ; |
1746 | 1746 | ||
1747 | if (mask & MAY_APPEND) | 1747 | if (mask & MAY_APPEND) |
1748 | av |= FILE__APPEND; | 1748 | av |= FILE__APPEND; |
1749 | else if (mask & MAY_WRITE) | 1749 | else if (mask & MAY_WRITE) |
1750 | av |= FILE__WRITE; | 1750 | av |= FILE__WRITE; |
1751 | 1751 | ||
1752 | } else { | 1752 | } else { |
1753 | if (mask & MAY_EXEC) | 1753 | if (mask & MAY_EXEC) |
1754 | av |= DIR__SEARCH; | 1754 | av |= DIR__SEARCH; |
1755 | if (mask & MAY_WRITE) | 1755 | if (mask & MAY_WRITE) |
1756 | av |= DIR__WRITE; | 1756 | av |= DIR__WRITE; |
1757 | if (mask & MAY_READ) | 1757 | if (mask & MAY_READ) |
1758 | av |= DIR__READ; | 1758 | av |= DIR__READ; |
1759 | } | 1759 | } |
1760 | 1760 | ||
1761 | return av; | 1761 | return av; |
1762 | } | 1762 | } |
1763 | 1763 | ||
1764 | /* Convert a Linux file to an access vector. */ | 1764 | /* Convert a Linux file to an access vector. */ |
1765 | static inline u32 file_to_av(struct file *file) | 1765 | static inline u32 file_to_av(struct file *file) |
1766 | { | 1766 | { |
1767 | u32 av = 0; | 1767 | u32 av = 0; |
1768 | 1768 | ||
1769 | if (file->f_mode & FMODE_READ) | 1769 | if (file->f_mode & FMODE_READ) |
1770 | av |= FILE__READ; | 1770 | av |= FILE__READ; |
1771 | if (file->f_mode & FMODE_WRITE) { | 1771 | if (file->f_mode & FMODE_WRITE) { |
1772 | if (file->f_flags & O_APPEND) | 1772 | if (file->f_flags & O_APPEND) |
1773 | av |= FILE__APPEND; | 1773 | av |= FILE__APPEND; |
1774 | else | 1774 | else |
1775 | av |= FILE__WRITE; | 1775 | av |= FILE__WRITE; |
1776 | } | 1776 | } |
1777 | if (!av) { | 1777 | if (!av) { |
1778 | /* | 1778 | /* |
1779 | * Special file opened with flags 3 for ioctl-only use. | 1779 | * Special file opened with flags 3 for ioctl-only use. |
1780 | */ | 1780 | */ |
1781 | av = FILE__IOCTL; | 1781 | av = FILE__IOCTL; |
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | return av; | 1784 | return av; |
1785 | } | 1785 | } |
1786 | 1786 | ||
1787 | /* | 1787 | /* |
1788 | * Convert a file to an access vector and include the correct open | 1788 | * Convert a file to an access vector and include the correct open |
1789 | * open permission. | 1789 | * open permission. |
1790 | */ | 1790 | */ |
1791 | static inline u32 open_file_to_av(struct file *file) | 1791 | static inline u32 open_file_to_av(struct file *file) |
1792 | { | 1792 | { |
1793 | u32 av = file_to_av(file); | 1793 | u32 av = file_to_av(file); |
1794 | 1794 | ||
1795 | if (selinux_policycap_openperm) | 1795 | if (selinux_policycap_openperm) |
1796 | av |= FILE__OPEN; | 1796 | av |= FILE__OPEN; |
1797 | 1797 | ||
1798 | return av; | 1798 | return av; |
1799 | } | 1799 | } |
1800 | 1800 | ||
1801 | /* Hook functions begin here. */ | 1801 | /* Hook functions begin here. */ |
1802 | 1802 | ||
1803 | static int selinux_ptrace_access_check(struct task_struct *child, | 1803 | static int selinux_ptrace_access_check(struct task_struct *child, |
1804 | unsigned int mode) | 1804 | unsigned int mode) |
1805 | { | 1805 | { |
1806 | int rc; | 1806 | int rc; |
1807 | 1807 | ||
1808 | rc = cap_ptrace_access_check(child, mode); | 1808 | rc = cap_ptrace_access_check(child, mode); |
1809 | if (rc) | 1809 | if (rc) |
1810 | return rc; | 1810 | return rc; |
1811 | 1811 | ||
1812 | if (mode & PTRACE_MODE_READ) { | 1812 | if (mode & PTRACE_MODE_READ) { |
1813 | u32 sid = current_sid(); | 1813 | u32 sid = current_sid(); |
1814 | u32 csid = task_sid(child); | 1814 | u32 csid = task_sid(child); |
1815 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 1815 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); |
1816 | } | 1816 | } |
1817 | 1817 | ||
1818 | return current_has_perm(child, PROCESS__PTRACE); | 1818 | return current_has_perm(child, PROCESS__PTRACE); |
1819 | } | 1819 | } |
1820 | 1820 | ||
1821 | static int selinux_ptrace_traceme(struct task_struct *parent) | 1821 | static int selinux_ptrace_traceme(struct task_struct *parent) |
1822 | { | 1822 | { |
1823 | int rc; | 1823 | int rc; |
1824 | 1824 | ||
1825 | rc = cap_ptrace_traceme(parent); | 1825 | rc = cap_ptrace_traceme(parent); |
1826 | if (rc) | 1826 | if (rc) |
1827 | return rc; | 1827 | return rc; |
1828 | 1828 | ||
1829 | return task_has_perm(parent, current, PROCESS__PTRACE); | 1829 | return task_has_perm(parent, current, PROCESS__PTRACE); |
1830 | } | 1830 | } |
1831 | 1831 | ||
1832 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 1832 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
1833 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 1833 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
1834 | { | 1834 | { |
1835 | int error; | 1835 | int error; |
1836 | 1836 | ||
1837 | error = current_has_perm(target, PROCESS__GETCAP); | 1837 | error = current_has_perm(target, PROCESS__GETCAP); |
1838 | if (error) | 1838 | if (error) |
1839 | return error; | 1839 | return error; |
1840 | 1840 | ||
1841 | return cap_capget(target, effective, inheritable, permitted); | 1841 | return cap_capget(target, effective, inheritable, permitted); |
1842 | } | 1842 | } |
1843 | 1843 | ||
1844 | static int selinux_capset(struct cred *new, const struct cred *old, | 1844 | static int selinux_capset(struct cred *new, const struct cred *old, |
1845 | const kernel_cap_t *effective, | 1845 | const kernel_cap_t *effective, |
1846 | const kernel_cap_t *inheritable, | 1846 | const kernel_cap_t *inheritable, |
1847 | const kernel_cap_t *permitted) | 1847 | const kernel_cap_t *permitted) |
1848 | { | 1848 | { |
1849 | int error; | 1849 | int error; |
1850 | 1850 | ||
1851 | error = cap_capset(new, old, | 1851 | error = cap_capset(new, old, |
1852 | effective, inheritable, permitted); | 1852 | effective, inheritable, permitted); |
1853 | if (error) | 1853 | if (error) |
1854 | return error; | 1854 | return error; |
1855 | 1855 | ||
1856 | return cred_has_perm(old, new, PROCESS__SETCAP); | 1856 | return cred_has_perm(old, new, PROCESS__SETCAP); |
1857 | } | 1857 | } |
1858 | 1858 | ||
1859 | /* | 1859 | /* |
1860 | * (This comment used to live with the selinux_task_setuid hook, | 1860 | * (This comment used to live with the selinux_task_setuid hook, |
1861 | * which was removed). | 1861 | * which was removed). |
1862 | * | 1862 | * |
1863 | * Since setuid only affects the current process, and since the SELinux | 1863 | * Since setuid only affects the current process, and since the SELinux |
1864 | * controls are not based on the Linux identity attributes, SELinux does not | 1864 | * controls are not based on the Linux identity attributes, SELinux does not |
1865 | * need to control this operation. However, SELinux does control the use of | 1865 | * need to control this operation. However, SELinux does control the use of |
1866 | * the CAP_SETUID and CAP_SETGID capabilities using the capable hook. | 1866 | * the CAP_SETUID and CAP_SETGID capabilities using the capable hook. |
1867 | */ | 1867 | */ |
1868 | 1868 | ||
1869 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, | 1869 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, |
1870 | int cap, int audit) | 1870 | int cap, int audit) |
1871 | { | 1871 | { |
1872 | int rc; | 1872 | int rc; |
1873 | 1873 | ||
1874 | rc = cap_capable(cred, ns, cap, audit); | 1874 | rc = cap_capable(cred, ns, cap, audit); |
1875 | if (rc) | 1875 | if (rc) |
1876 | return rc; | 1876 | return rc; |
1877 | 1877 | ||
1878 | return cred_has_capability(cred, cap, audit); | 1878 | return cred_has_capability(cred, cap, audit); |
1879 | } | 1879 | } |
1880 | 1880 | ||
1881 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) | 1881 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
1882 | { | 1882 | { |
1883 | const struct cred *cred = current_cred(); | 1883 | const struct cred *cred = current_cred(); |
1884 | int rc = 0; | 1884 | int rc = 0; |
1885 | 1885 | ||
1886 | if (!sb) | 1886 | if (!sb) |
1887 | return 0; | 1887 | return 0; |
1888 | 1888 | ||
1889 | switch (cmds) { | 1889 | switch (cmds) { |
1890 | case Q_SYNC: | 1890 | case Q_SYNC: |
1891 | case Q_QUOTAON: | 1891 | case Q_QUOTAON: |
1892 | case Q_QUOTAOFF: | 1892 | case Q_QUOTAOFF: |
1893 | case Q_SETINFO: | 1893 | case Q_SETINFO: |
1894 | case Q_SETQUOTA: | 1894 | case Q_SETQUOTA: |
1895 | rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL); | 1895 | rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL); |
1896 | break; | 1896 | break; |
1897 | case Q_GETFMT: | 1897 | case Q_GETFMT: |
1898 | case Q_GETINFO: | 1898 | case Q_GETINFO: |
1899 | case Q_GETQUOTA: | 1899 | case Q_GETQUOTA: |
1900 | rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL); | 1900 | rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL); |
1901 | break; | 1901 | break; |
1902 | default: | 1902 | default: |
1903 | rc = 0; /* let the kernel handle invalid cmds */ | 1903 | rc = 0; /* let the kernel handle invalid cmds */ |
1904 | break; | 1904 | break; |
1905 | } | 1905 | } |
1906 | return rc; | 1906 | return rc; |
1907 | } | 1907 | } |
1908 | 1908 | ||
1909 | static int selinux_quota_on(struct dentry *dentry) | 1909 | static int selinux_quota_on(struct dentry *dentry) |
1910 | { | 1910 | { |
1911 | const struct cred *cred = current_cred(); | 1911 | const struct cred *cred = current_cred(); |
1912 | 1912 | ||
1913 | return dentry_has_perm(cred, dentry, FILE__QUOTAON); | 1913 | return dentry_has_perm(cred, dentry, FILE__QUOTAON); |
1914 | } | 1914 | } |
1915 | 1915 | ||
1916 | static int selinux_syslog(int type) | 1916 | static int selinux_syslog(int type) |
1917 | { | 1917 | { |
1918 | int rc; | 1918 | int rc; |
1919 | 1919 | ||
1920 | switch (type) { | 1920 | switch (type) { |
1921 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ | 1921 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
1922 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ | 1922 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
1923 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 1923 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
1924 | break; | 1924 | break; |
1925 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ | 1925 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
1926 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ | 1926 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
1927 | /* Set level of messages printed to console */ | 1927 | /* Set level of messages printed to console */ |
1928 | case SYSLOG_ACTION_CONSOLE_LEVEL: | 1928 | case SYSLOG_ACTION_CONSOLE_LEVEL: |
1929 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 1929 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
1930 | break; | 1930 | break; |
1931 | case SYSLOG_ACTION_CLOSE: /* Close log */ | 1931 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
1932 | case SYSLOG_ACTION_OPEN: /* Open log */ | 1932 | case SYSLOG_ACTION_OPEN: /* Open log */ |
1933 | case SYSLOG_ACTION_READ: /* Read from log */ | 1933 | case SYSLOG_ACTION_READ: /* Read from log */ |
1934 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ | 1934 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
1935 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ | 1935 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
1936 | default: | 1936 | default: |
1937 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 1937 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
1938 | break; | 1938 | break; |
1939 | } | 1939 | } |
1940 | return rc; | 1940 | return rc; |
1941 | } | 1941 | } |
1942 | 1942 | ||
1943 | /* | 1943 | /* |
1944 | * Check that a process has enough memory to allocate a new virtual | 1944 | * Check that a process has enough memory to allocate a new virtual |
1945 | * mapping. 0 means there is enough memory for the allocation to | 1945 | * mapping. 0 means there is enough memory for the allocation to |
1946 | * succeed and -ENOMEM implies there is not. | 1946 | * succeed and -ENOMEM implies there is not. |
1947 | * | 1947 | * |
1948 | * Do not audit the selinux permission check, as this is applied to all | 1948 | * Do not audit the selinux permission check, as this is applied to all |
1949 | * processes that allocate mappings. | 1949 | * processes that allocate mappings. |
1950 | */ | 1950 | */ |
1951 | static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | 1951 | static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) |
1952 | { | 1952 | { |
1953 | int rc, cap_sys_admin = 0; | 1953 | int rc, cap_sys_admin = 0; |
1954 | 1954 | ||
1955 | rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, | 1955 | rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, |
1956 | SECURITY_CAP_NOAUDIT); | 1956 | SECURITY_CAP_NOAUDIT); |
1957 | if (rc == 0) | 1957 | if (rc == 0) |
1958 | cap_sys_admin = 1; | 1958 | cap_sys_admin = 1; |
1959 | 1959 | ||
1960 | return __vm_enough_memory(mm, pages, cap_sys_admin); | 1960 | return __vm_enough_memory(mm, pages, cap_sys_admin); |
1961 | } | 1961 | } |
1962 | 1962 | ||
1963 | /* binprm security operations */ | 1963 | /* binprm security operations */ |
1964 | 1964 | ||
1965 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) | 1965 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) |
1966 | { | 1966 | { |
1967 | const struct task_security_struct *old_tsec; | 1967 | const struct task_security_struct *old_tsec; |
1968 | struct task_security_struct *new_tsec; | 1968 | struct task_security_struct *new_tsec; |
1969 | struct inode_security_struct *isec; | 1969 | struct inode_security_struct *isec; |
1970 | struct common_audit_data ad; | 1970 | struct common_audit_data ad; |
1971 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 1971 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
1972 | int rc; | 1972 | int rc; |
1973 | 1973 | ||
1974 | rc = cap_bprm_set_creds(bprm); | 1974 | rc = cap_bprm_set_creds(bprm); |
1975 | if (rc) | 1975 | if (rc) |
1976 | return rc; | 1976 | return rc; |
1977 | 1977 | ||
1978 | /* SELinux context only depends on initial program or script and not | 1978 | /* SELinux context only depends on initial program or script and not |
1979 | * the script interpreter */ | 1979 | * the script interpreter */ |
1980 | if (bprm->cred_prepared) | 1980 | if (bprm->cred_prepared) |
1981 | return 0; | 1981 | return 0; |
1982 | 1982 | ||
1983 | old_tsec = current_security(); | 1983 | old_tsec = current_security(); |
1984 | new_tsec = bprm->cred->security; | 1984 | new_tsec = bprm->cred->security; |
1985 | isec = inode->i_security; | 1985 | isec = inode->i_security; |
1986 | 1986 | ||
1987 | /* Default to the current task SID. */ | 1987 | /* Default to the current task SID. */ |
1988 | new_tsec->sid = old_tsec->sid; | 1988 | new_tsec->sid = old_tsec->sid; |
1989 | new_tsec->osid = old_tsec->sid; | 1989 | new_tsec->osid = old_tsec->sid; |
1990 | 1990 | ||
1991 | /* Reset fs, key, and sock SIDs on execve. */ | 1991 | /* Reset fs, key, and sock SIDs on execve. */ |
1992 | new_tsec->create_sid = 0; | 1992 | new_tsec->create_sid = 0; |
1993 | new_tsec->keycreate_sid = 0; | 1993 | new_tsec->keycreate_sid = 0; |
1994 | new_tsec->sockcreate_sid = 0; | 1994 | new_tsec->sockcreate_sid = 0; |
1995 | 1995 | ||
1996 | if (old_tsec->exec_sid) { | 1996 | if (old_tsec->exec_sid) { |
1997 | new_tsec->sid = old_tsec->exec_sid; | 1997 | new_tsec->sid = old_tsec->exec_sid; |
1998 | /* Reset exec SID on execve. */ | 1998 | /* Reset exec SID on execve. */ |
1999 | new_tsec->exec_sid = 0; | 1999 | new_tsec->exec_sid = 0; |
2000 | } else { | 2000 | } else { |
2001 | /* Check for a default transition on this program. */ | 2001 | /* Check for a default transition on this program. */ |
2002 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 2002 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
2003 | SECCLASS_PROCESS, NULL, | 2003 | SECCLASS_PROCESS, NULL, |
2004 | &new_tsec->sid); | 2004 | &new_tsec->sid); |
2005 | if (rc) | 2005 | if (rc) |
2006 | return rc; | 2006 | return rc; |
2007 | } | 2007 | } |
2008 | 2008 | ||
2009 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 2009 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
2010 | ad.u.path = bprm->file->f_path; | 2010 | ad.u.path = bprm->file->f_path; |
2011 | 2011 | ||
2012 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2012 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
2013 | new_tsec->sid = old_tsec->sid; | 2013 | new_tsec->sid = old_tsec->sid; |
2014 | 2014 | ||
2015 | if (new_tsec->sid == old_tsec->sid) { | 2015 | if (new_tsec->sid == old_tsec->sid) { |
2016 | rc = avc_has_perm(old_tsec->sid, isec->sid, | 2016 | rc = avc_has_perm(old_tsec->sid, isec->sid, |
2017 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); | 2017 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); |
2018 | if (rc) | 2018 | if (rc) |
2019 | return rc; | 2019 | return rc; |
2020 | } else { | 2020 | } else { |
2021 | /* Check permissions for the transition. */ | 2021 | /* Check permissions for the transition. */ |
2022 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2022 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, |
2023 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); | 2023 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); |
2024 | if (rc) | 2024 | if (rc) |
2025 | return rc; | 2025 | return rc; |
2026 | 2026 | ||
2027 | rc = avc_has_perm(new_tsec->sid, isec->sid, | 2027 | rc = avc_has_perm(new_tsec->sid, isec->sid, |
2028 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); | 2028 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); |
2029 | if (rc) | 2029 | if (rc) |
2030 | return rc; | 2030 | return rc; |
2031 | 2031 | ||
2032 | /* Check for shared state */ | 2032 | /* Check for shared state */ |
2033 | if (bprm->unsafe & LSM_UNSAFE_SHARE) { | 2033 | if (bprm->unsafe & LSM_UNSAFE_SHARE) { |
2034 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | 2034 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, |
2035 | SECCLASS_PROCESS, PROCESS__SHARE, | 2035 | SECCLASS_PROCESS, PROCESS__SHARE, |
2036 | NULL); | 2036 | NULL); |
2037 | if (rc) | 2037 | if (rc) |
2038 | return -EPERM; | 2038 | return -EPERM; |
2039 | } | 2039 | } |
2040 | 2040 | ||
2041 | /* Make sure that anyone attempting to ptrace over a task that | 2041 | /* Make sure that anyone attempting to ptrace over a task that |
2042 | * changes its SID has the appropriate permit */ | 2042 | * changes its SID has the appropriate permit */ |
2043 | if (bprm->unsafe & | 2043 | if (bprm->unsafe & |
2044 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | 2044 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { |
2045 | struct task_struct *tracer; | 2045 | struct task_struct *tracer; |
2046 | struct task_security_struct *sec; | 2046 | struct task_security_struct *sec; |
2047 | u32 ptsid = 0; | 2047 | u32 ptsid = 0; |
2048 | 2048 | ||
2049 | rcu_read_lock(); | 2049 | rcu_read_lock(); |
2050 | tracer = ptrace_parent(current); | 2050 | tracer = ptrace_parent(current); |
2051 | if (likely(tracer != NULL)) { | 2051 | if (likely(tracer != NULL)) { |
2052 | sec = __task_cred(tracer)->security; | 2052 | sec = __task_cred(tracer)->security; |
2053 | ptsid = sec->sid; | 2053 | ptsid = sec->sid; |
2054 | } | 2054 | } |
2055 | rcu_read_unlock(); | 2055 | rcu_read_unlock(); |
2056 | 2056 | ||
2057 | if (ptsid != 0) { | 2057 | if (ptsid != 0) { |
2058 | rc = avc_has_perm(ptsid, new_tsec->sid, | 2058 | rc = avc_has_perm(ptsid, new_tsec->sid, |
2059 | SECCLASS_PROCESS, | 2059 | SECCLASS_PROCESS, |
2060 | PROCESS__PTRACE, NULL); | 2060 | PROCESS__PTRACE, NULL); |
2061 | if (rc) | 2061 | if (rc) |
2062 | return -EPERM; | 2062 | return -EPERM; |
2063 | } | 2063 | } |
2064 | } | 2064 | } |
2065 | 2065 | ||
2066 | /* Clear any possibly unsafe personality bits on exec: */ | 2066 | /* Clear any possibly unsafe personality bits on exec: */ |
2067 | bprm->per_clear |= PER_CLEAR_ON_SETID; | 2067 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
2068 | } | 2068 | } |
2069 | 2069 | ||
2070 | return 0; | 2070 | return 0; |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2073 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
2074 | { | 2074 | { |
2075 | const struct task_security_struct *tsec = current_security(); | 2075 | const struct task_security_struct *tsec = current_security(); |
2076 | u32 sid, osid; | 2076 | u32 sid, osid; |
2077 | int atsecure = 0; | 2077 | int atsecure = 0; |
2078 | 2078 | ||
2079 | sid = tsec->sid; | 2079 | sid = tsec->sid; |
2080 | osid = tsec->osid; | 2080 | osid = tsec->osid; |
2081 | 2081 | ||
2082 | if (osid != sid) { | 2082 | if (osid != sid) { |
2083 | /* Enable secure mode for SIDs transitions unless | 2083 | /* Enable secure mode for SIDs transitions unless |
2084 | the noatsecure permission is granted between | 2084 | the noatsecure permission is granted between |
2085 | the two SIDs, i.e. ahp returns 0. */ | 2085 | the two SIDs, i.e. ahp returns 0. */ |
2086 | atsecure = avc_has_perm(osid, sid, | 2086 | atsecure = avc_has_perm(osid, sid, |
2087 | SECCLASS_PROCESS, | 2087 | SECCLASS_PROCESS, |
2088 | PROCESS__NOATSECURE, NULL); | 2088 | PROCESS__NOATSECURE, NULL); |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | return (atsecure || cap_bprm_secureexec(bprm)); | 2091 | return (atsecure || cap_bprm_secureexec(bprm)); |
2092 | } | 2092 | } |
2093 | 2093 | ||
2094 | /* Derived from fs/exec.c:flush_old_files. */ | 2094 | /* Derived from fs/exec.c:flush_old_files. */ |
2095 | static inline void flush_unauthorized_files(const struct cred *cred, | 2095 | static inline void flush_unauthorized_files(const struct cred *cred, |
2096 | struct files_struct *files) | 2096 | struct files_struct *files) |
2097 | { | 2097 | { |
2098 | struct common_audit_data ad; | 2098 | struct common_audit_data ad; |
2099 | struct file *file, *devnull = NULL; | 2099 | struct file *file, *devnull = NULL; |
2100 | struct tty_struct *tty; | 2100 | struct tty_struct *tty; |
2101 | struct fdtable *fdt; | 2101 | struct fdtable *fdt; |
2102 | long j = -1; | 2102 | long j = -1; |
2103 | int drop_tty = 0; | 2103 | int drop_tty = 0; |
2104 | 2104 | ||
2105 | tty = get_current_tty(); | 2105 | tty = get_current_tty(); |
2106 | if (tty) { | 2106 | if (tty) { |
2107 | spin_lock(&tty_files_lock); | 2107 | spin_lock(&tty_files_lock); |
2108 | if (!list_empty(&tty->tty_files)) { | 2108 | if (!list_empty(&tty->tty_files)) { |
2109 | struct tty_file_private *file_priv; | 2109 | struct tty_file_private *file_priv; |
2110 | struct inode *inode; | 2110 | struct inode *inode; |
2111 | 2111 | ||
2112 | /* Revalidate access to controlling tty. | 2112 | /* Revalidate access to controlling tty. |
2113 | Use inode_has_perm on the tty inode directly rather | 2113 | Use inode_has_perm on the tty inode directly rather |
2114 | than using file_has_perm, as this particular open | 2114 | than using file_has_perm, as this particular open |
2115 | file may belong to another process and we are only | 2115 | file may belong to another process and we are only |
2116 | interested in the inode-based check here. */ | 2116 | interested in the inode-based check here. */ |
2117 | file_priv = list_first_entry(&tty->tty_files, | 2117 | file_priv = list_first_entry(&tty->tty_files, |
2118 | struct tty_file_private, list); | 2118 | struct tty_file_private, list); |
2119 | file = file_priv->file; | 2119 | file = file_priv->file; |
2120 | inode = file->f_path.dentry->d_inode; | 2120 | inode = file->f_path.dentry->d_inode; |
2121 | if (inode_has_perm_noadp(cred, inode, | 2121 | if (inode_has_perm_noadp(cred, inode, |
2122 | FILE__READ | FILE__WRITE, 0)) { | 2122 | FILE__READ | FILE__WRITE, 0)) { |
2123 | drop_tty = 1; | 2123 | drop_tty = 1; |
2124 | } | 2124 | } |
2125 | } | 2125 | } |
2126 | spin_unlock(&tty_files_lock); | 2126 | spin_unlock(&tty_files_lock); |
2127 | tty_kref_put(tty); | 2127 | tty_kref_put(tty); |
2128 | } | 2128 | } |
2129 | /* Reset controlling tty. */ | 2129 | /* Reset controlling tty. */ |
2130 | if (drop_tty) | 2130 | if (drop_tty) |
2131 | no_tty(); | 2131 | no_tty(); |
2132 | 2132 | ||
2133 | /* Revalidate access to inherited open files. */ | 2133 | /* Revalidate access to inherited open files. */ |
2134 | 2134 | ||
2135 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | 2135 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2136 | 2136 | ||
2137 | spin_lock(&files->file_lock); | 2137 | spin_lock(&files->file_lock); |
2138 | for (;;) { | 2138 | for (;;) { |
2139 | unsigned long set, i; | 2139 | unsigned long set, i; |
2140 | int fd; | 2140 | int fd; |
2141 | 2141 | ||
2142 | j++; | 2142 | j++; |
2143 | i = j * __NFDBITS; | 2143 | i = j * __NFDBITS; |
2144 | fdt = files_fdtable(files); | 2144 | fdt = files_fdtable(files); |
2145 | if (i >= fdt->max_fds) | 2145 | if (i >= fdt->max_fds) |
2146 | break; | 2146 | break; |
2147 | set = fdt->open_fds->fds_bits[j]; | 2147 | set = fdt->open_fds->fds_bits[j]; |
2148 | if (!set) | 2148 | if (!set) |
2149 | continue; | 2149 | continue; |
2150 | spin_unlock(&files->file_lock); | 2150 | spin_unlock(&files->file_lock); |
2151 | for ( ; set ; i++, set >>= 1) { | 2151 | for ( ; set ; i++, set >>= 1) { |
2152 | if (set & 1) { | 2152 | if (set & 1) { |
2153 | file = fget(i); | 2153 | file = fget(i); |
2154 | if (!file) | 2154 | if (!file) |
2155 | continue; | 2155 | continue; |
2156 | if (file_has_perm(cred, | 2156 | if (file_has_perm(cred, |
2157 | file, | 2157 | file, |
2158 | file_to_av(file))) { | 2158 | file_to_av(file))) { |
2159 | sys_close(i); | 2159 | sys_close(i); |
2160 | fd = get_unused_fd(); | 2160 | fd = get_unused_fd(); |
2161 | if (fd != i) { | 2161 | if (fd != i) { |
2162 | if (fd >= 0) | 2162 | if (fd >= 0) |
2163 | put_unused_fd(fd); | 2163 | put_unused_fd(fd); |
2164 | fput(file); | 2164 | fput(file); |
2165 | continue; | 2165 | continue; |
2166 | } | 2166 | } |
2167 | if (devnull) { | 2167 | if (devnull) { |
2168 | get_file(devnull); | 2168 | get_file(devnull); |
2169 | } else { | 2169 | } else { |
2170 | devnull = dentry_open( | 2170 | devnull = dentry_open( |
2171 | dget(selinux_null), | 2171 | dget(selinux_null), |
2172 | mntget(selinuxfs_mount), | 2172 | mntget(selinuxfs_mount), |
2173 | O_RDWR, cred); | 2173 | O_RDWR, cred); |
2174 | if (IS_ERR(devnull)) { | 2174 | if (IS_ERR(devnull)) { |
2175 | devnull = NULL; | 2175 | devnull = NULL; |
2176 | put_unused_fd(fd); | 2176 | put_unused_fd(fd); |
2177 | fput(file); | 2177 | fput(file); |
2178 | continue; | 2178 | continue; |
2179 | } | 2179 | } |
2180 | } | 2180 | } |
2181 | fd_install(fd, devnull); | 2181 | fd_install(fd, devnull); |
2182 | } | 2182 | } |
2183 | fput(file); | 2183 | fput(file); |
2184 | } | 2184 | } |
2185 | } | 2185 | } |
2186 | spin_lock(&files->file_lock); | 2186 | spin_lock(&files->file_lock); |
2187 | 2187 | ||
2188 | } | 2188 | } |
2189 | spin_unlock(&files->file_lock); | 2189 | spin_unlock(&files->file_lock); |
2190 | } | 2190 | } |
2191 | 2191 | ||
2192 | /* | 2192 | /* |
2193 | * Prepare a process for imminent new credential changes due to exec | 2193 | * Prepare a process for imminent new credential changes due to exec |
2194 | */ | 2194 | */ |
2195 | static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | 2195 | static void selinux_bprm_committing_creds(struct linux_binprm *bprm) |
2196 | { | 2196 | { |
2197 | struct task_security_struct *new_tsec; | 2197 | struct task_security_struct *new_tsec; |
2198 | struct rlimit *rlim, *initrlim; | 2198 | struct rlimit *rlim, *initrlim; |
2199 | int rc, i; | 2199 | int rc, i; |
2200 | 2200 | ||
2201 | new_tsec = bprm->cred->security; | 2201 | new_tsec = bprm->cred->security; |
2202 | if (new_tsec->sid == new_tsec->osid) | 2202 | if (new_tsec->sid == new_tsec->osid) |
2203 | return; | 2203 | return; |
2204 | 2204 | ||
2205 | /* Close files for which the new task SID is not authorized. */ | 2205 | /* Close files for which the new task SID is not authorized. */ |
2206 | flush_unauthorized_files(bprm->cred, current->files); | 2206 | flush_unauthorized_files(bprm->cred, current->files); |
2207 | 2207 | ||
2208 | /* Always clear parent death signal on SID transitions. */ | 2208 | /* Always clear parent death signal on SID transitions. */ |
2209 | current->pdeath_signal = 0; | 2209 | current->pdeath_signal = 0; |
2210 | 2210 | ||
2211 | /* Check whether the new SID can inherit resource limits from the old | 2211 | /* Check whether the new SID can inherit resource limits from the old |
2212 | * SID. If not, reset all soft limits to the lower of the current | 2212 | * SID. If not, reset all soft limits to the lower of the current |
2213 | * task's hard limit and the init task's soft limit. | 2213 | * task's hard limit and the init task's soft limit. |
2214 | * | 2214 | * |
2215 | * Note that the setting of hard limits (even to lower them) can be | 2215 | * Note that the setting of hard limits (even to lower them) can be |
2216 | * controlled by the setrlimit check. The inclusion of the init task's | 2216 | * controlled by the setrlimit check. The inclusion of the init task's |
2217 | * soft limit into the computation is to avoid resetting soft limits | 2217 | * soft limit into the computation is to avoid resetting soft limits |
2218 | * higher than the default soft limit for cases where the default is | 2218 | * higher than the default soft limit for cases where the default is |
2219 | * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. | 2219 | * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. |
2220 | */ | 2220 | */ |
2221 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2221 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, |
2222 | PROCESS__RLIMITINH, NULL); | 2222 | PROCESS__RLIMITINH, NULL); |
2223 | if (rc) { | 2223 | if (rc) { |
2224 | /* protect against do_prlimit() */ | 2224 | /* protect against do_prlimit() */ |
2225 | task_lock(current); | 2225 | task_lock(current); |
2226 | for (i = 0; i < RLIM_NLIMITS; i++) { | 2226 | for (i = 0; i < RLIM_NLIMITS; i++) { |
2227 | rlim = current->signal->rlim + i; | 2227 | rlim = current->signal->rlim + i; |
2228 | initrlim = init_task.signal->rlim + i; | 2228 | initrlim = init_task.signal->rlim + i; |
2229 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2229 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2230 | } | 2230 | } |
2231 | task_unlock(current); | 2231 | task_unlock(current); |
2232 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); | 2232 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); |
2233 | } | 2233 | } |
2234 | } | 2234 | } |
2235 | 2235 | ||
2236 | /* | 2236 | /* |
2237 | * Clean up the process immediately after the installation of new credentials | 2237 | * Clean up the process immediately after the installation of new credentials |
2238 | * due to exec | 2238 | * due to exec |
2239 | */ | 2239 | */ |
2240 | static void selinux_bprm_committed_creds(struct linux_binprm *bprm) | 2240 | static void selinux_bprm_committed_creds(struct linux_binprm *bprm) |
2241 | { | 2241 | { |
2242 | const struct task_security_struct *tsec = current_security(); | 2242 | const struct task_security_struct *tsec = current_security(); |
2243 | struct itimerval itimer; | 2243 | struct itimerval itimer; |
2244 | u32 osid, sid; | 2244 | u32 osid, sid; |
2245 | int rc, i; | 2245 | int rc, i; |
2246 | 2246 | ||
2247 | osid = tsec->osid; | 2247 | osid = tsec->osid; |
2248 | sid = tsec->sid; | 2248 | sid = tsec->sid; |
2249 | 2249 | ||
2250 | if (sid == osid) | 2250 | if (sid == osid) |
2251 | return; | 2251 | return; |
2252 | 2252 | ||
2253 | /* Check whether the new SID can inherit signal state from the old SID. | 2253 | /* Check whether the new SID can inherit signal state from the old SID. |
2254 | * If not, clear itimers to avoid subsequent signal generation and | 2254 | * If not, clear itimers to avoid subsequent signal generation and |
2255 | * flush and unblock signals. | 2255 | * flush and unblock signals. |
2256 | * | 2256 | * |
2257 | * This must occur _after_ the task SID has been updated so that any | 2257 | * This must occur _after_ the task SID has been updated so that any |
2258 | * kill done after the flush will be checked against the new SID. | 2258 | * kill done after the flush will be checked against the new SID. |
2259 | */ | 2259 | */ |
2260 | rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); | 2260 | rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); |
2261 | if (rc) { | 2261 | if (rc) { |
2262 | memset(&itimer, 0, sizeof itimer); | 2262 | memset(&itimer, 0, sizeof itimer); |
2263 | for (i = 0; i < 3; i++) | 2263 | for (i = 0; i < 3; i++) |
2264 | do_setitimer(i, &itimer, NULL); | 2264 | do_setitimer(i, &itimer, NULL); |
2265 | spin_lock_irq(¤t->sighand->siglock); | 2265 | spin_lock_irq(¤t->sighand->siglock); |
2266 | if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { | 2266 | if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { |
2267 | __flush_signals(current); | 2267 | __flush_signals(current); |
2268 | flush_signal_handlers(current, 1); | 2268 | flush_signal_handlers(current, 1); |
2269 | sigemptyset(¤t->blocked); | 2269 | sigemptyset(¤t->blocked); |
2270 | } | 2270 | } |
2271 | spin_unlock_irq(¤t->sighand->siglock); | 2271 | spin_unlock_irq(¤t->sighand->siglock); |
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | /* Wake up the parent if it is waiting so that it can recheck | 2274 | /* Wake up the parent if it is waiting so that it can recheck |
2275 | * wait permission to the new task SID. */ | 2275 | * wait permission to the new task SID. */ |
2276 | read_lock(&tasklist_lock); | 2276 | read_lock(&tasklist_lock); |
2277 | __wake_up_parent(current, current->real_parent); | 2277 | __wake_up_parent(current, current->real_parent); |
2278 | read_unlock(&tasklist_lock); | 2278 | read_unlock(&tasklist_lock); |
2279 | } | 2279 | } |
2280 | 2280 | ||
2281 | /* superblock security operations */ | 2281 | /* superblock security operations */ |
2282 | 2282 | ||
2283 | static int selinux_sb_alloc_security(struct super_block *sb) | 2283 | static int selinux_sb_alloc_security(struct super_block *sb) |
2284 | { | 2284 | { |
2285 | return superblock_alloc_security(sb); | 2285 | return superblock_alloc_security(sb); |
2286 | } | 2286 | } |
2287 | 2287 | ||
2288 | static void selinux_sb_free_security(struct super_block *sb) | 2288 | static void selinux_sb_free_security(struct super_block *sb) |
2289 | { | 2289 | { |
2290 | superblock_free_security(sb); | 2290 | superblock_free_security(sb); |
2291 | } | 2291 | } |
2292 | 2292 | ||
2293 | static inline int match_prefix(char *prefix, int plen, char *option, int olen) | 2293 | static inline int match_prefix(char *prefix, int plen, char *option, int olen) |
2294 | { | 2294 | { |
2295 | if (plen > olen) | 2295 | if (plen > olen) |
2296 | return 0; | 2296 | return 0; |
2297 | 2297 | ||
2298 | return !memcmp(prefix, option, plen); | 2298 | return !memcmp(prefix, option, plen); |
2299 | } | 2299 | } |
2300 | 2300 | ||
2301 | static inline int selinux_option(char *option, int len) | 2301 | static inline int selinux_option(char *option, int len) |
2302 | { | 2302 | { |
2303 | return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || | 2303 | return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || |
2304 | match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || | 2304 | match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || |
2305 | match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || | 2305 | match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || |
2306 | match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || | 2306 | match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || |
2307 | match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); | 2307 | match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); |
2308 | } | 2308 | } |
2309 | 2309 | ||
2310 | static inline void take_option(char **to, char *from, int *first, int len) | 2310 | static inline void take_option(char **to, char *from, int *first, int len) |
2311 | { | 2311 | { |
2312 | if (!*first) { | 2312 | if (!*first) { |
2313 | **to = ','; | 2313 | **to = ','; |
2314 | *to += 1; | 2314 | *to += 1; |
2315 | } else | 2315 | } else |
2316 | *first = 0; | 2316 | *first = 0; |
2317 | memcpy(*to, from, len); | 2317 | memcpy(*to, from, len); |
2318 | *to += len; | 2318 | *to += len; |
2319 | } | 2319 | } |
2320 | 2320 | ||
2321 | static inline void take_selinux_option(char **to, char *from, int *first, | 2321 | static inline void take_selinux_option(char **to, char *from, int *first, |
2322 | int len) | 2322 | int len) |
2323 | { | 2323 | { |
2324 | int current_size = 0; | 2324 | int current_size = 0; |
2325 | 2325 | ||
2326 | if (!*first) { | 2326 | if (!*first) { |
2327 | **to = '|'; | 2327 | **to = '|'; |
2328 | *to += 1; | 2328 | *to += 1; |
2329 | } else | 2329 | } else |
2330 | *first = 0; | 2330 | *first = 0; |
2331 | 2331 | ||
2332 | while (current_size < len) { | 2332 | while (current_size < len) { |
2333 | if (*from != '"') { | 2333 | if (*from != '"') { |
2334 | **to = *from; | 2334 | **to = *from; |
2335 | *to += 1; | 2335 | *to += 1; |
2336 | } | 2336 | } |
2337 | from += 1; | 2337 | from += 1; |
2338 | current_size += 1; | 2338 | current_size += 1; |
2339 | } | 2339 | } |
2340 | } | 2340 | } |
2341 | 2341 | ||
2342 | static int selinux_sb_copy_data(char *orig, char *copy) | 2342 | static int selinux_sb_copy_data(char *orig, char *copy) |
2343 | { | 2343 | { |
2344 | int fnosec, fsec, rc = 0; | 2344 | int fnosec, fsec, rc = 0; |
2345 | char *in_save, *in_curr, *in_end; | 2345 | char *in_save, *in_curr, *in_end; |
2346 | char *sec_curr, *nosec_save, *nosec; | 2346 | char *sec_curr, *nosec_save, *nosec; |
2347 | int open_quote = 0; | 2347 | int open_quote = 0; |
2348 | 2348 | ||
2349 | in_curr = orig; | 2349 | in_curr = orig; |
2350 | sec_curr = copy; | 2350 | sec_curr = copy; |
2351 | 2351 | ||
2352 | nosec = (char *)get_zeroed_page(GFP_KERNEL); | 2352 | nosec = (char *)get_zeroed_page(GFP_KERNEL); |
2353 | if (!nosec) { | 2353 | if (!nosec) { |
2354 | rc = -ENOMEM; | 2354 | rc = -ENOMEM; |
2355 | goto out; | 2355 | goto out; |
2356 | } | 2356 | } |
2357 | 2357 | ||
2358 | nosec_save = nosec; | 2358 | nosec_save = nosec; |
2359 | fnosec = fsec = 1; | 2359 | fnosec = fsec = 1; |
2360 | in_save = in_end = orig; | 2360 | in_save = in_end = orig; |
2361 | 2361 | ||
2362 | do { | 2362 | do { |
2363 | if (*in_end == '"') | 2363 | if (*in_end == '"') |
2364 | open_quote = !open_quote; | 2364 | open_quote = !open_quote; |
2365 | if ((*in_end == ',' && open_quote == 0) || | 2365 | if ((*in_end == ',' && open_quote == 0) || |
2366 | *in_end == '\0') { | 2366 | *in_end == '\0') { |
2367 | int len = in_end - in_curr; | 2367 | int len = in_end - in_curr; |
2368 | 2368 | ||
2369 | if (selinux_option(in_curr, len)) | 2369 | if (selinux_option(in_curr, len)) |
2370 | take_selinux_option(&sec_curr, in_curr, &fsec, len); | 2370 | take_selinux_option(&sec_curr, in_curr, &fsec, len); |
2371 | else | 2371 | else |
2372 | take_option(&nosec, in_curr, &fnosec, len); | 2372 | take_option(&nosec, in_curr, &fnosec, len); |
2373 | 2373 | ||
2374 | in_curr = in_end + 1; | 2374 | in_curr = in_end + 1; |
2375 | } | 2375 | } |
2376 | } while (*in_end++); | 2376 | } while (*in_end++); |
2377 | 2377 | ||
2378 | strcpy(in_save, nosec_save); | 2378 | strcpy(in_save, nosec_save); |
2379 | free_page((unsigned long)nosec_save); | 2379 | free_page((unsigned long)nosec_save); |
2380 | out: | 2380 | out: |
2381 | return rc; | 2381 | return rc; |
2382 | } | 2382 | } |
2383 | 2383 | ||
2384 | static int selinux_sb_remount(struct super_block *sb, void *data) | 2384 | static int selinux_sb_remount(struct super_block *sb, void *data) |
2385 | { | 2385 | { |
2386 | int rc, i, *flags; | 2386 | int rc, i, *flags; |
2387 | struct security_mnt_opts opts; | 2387 | struct security_mnt_opts opts; |
2388 | char *secdata, **mount_options; | 2388 | char *secdata, **mount_options; |
2389 | struct superblock_security_struct *sbsec = sb->s_security; | 2389 | struct superblock_security_struct *sbsec = sb->s_security; |
2390 | 2390 | ||
2391 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 2391 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
2392 | return 0; | 2392 | return 0; |
2393 | 2393 | ||
2394 | if (!data) | 2394 | if (!data) |
2395 | return 0; | 2395 | return 0; |
2396 | 2396 | ||
2397 | if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) | 2397 | if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) |
2398 | return 0; | 2398 | return 0; |
2399 | 2399 | ||
2400 | security_init_mnt_opts(&opts); | 2400 | security_init_mnt_opts(&opts); |
2401 | secdata = alloc_secdata(); | 2401 | secdata = alloc_secdata(); |
2402 | if (!secdata) | 2402 | if (!secdata) |
2403 | return -ENOMEM; | 2403 | return -ENOMEM; |
2404 | rc = selinux_sb_copy_data(data, secdata); | 2404 | rc = selinux_sb_copy_data(data, secdata); |
2405 | if (rc) | 2405 | if (rc) |
2406 | goto out_free_secdata; | 2406 | goto out_free_secdata; |
2407 | 2407 | ||
2408 | rc = selinux_parse_opts_str(secdata, &opts); | 2408 | rc = selinux_parse_opts_str(secdata, &opts); |
2409 | if (rc) | 2409 | if (rc) |
2410 | goto out_free_secdata; | 2410 | goto out_free_secdata; |
2411 | 2411 | ||
2412 | mount_options = opts.mnt_opts; | 2412 | mount_options = opts.mnt_opts; |
2413 | flags = opts.mnt_opts_flags; | 2413 | flags = opts.mnt_opts_flags; |
2414 | 2414 | ||
2415 | for (i = 0; i < opts.num_mnt_opts; i++) { | 2415 | for (i = 0; i < opts.num_mnt_opts; i++) { |
2416 | u32 sid; | 2416 | u32 sid; |
2417 | size_t len; | 2417 | size_t len; |
2418 | 2418 | ||
2419 | if (flags[i] == SE_SBLABELSUPP) | 2419 | if (flags[i] == SE_SBLABELSUPP) |
2420 | continue; | 2420 | continue; |
2421 | len = strlen(mount_options[i]); | 2421 | len = strlen(mount_options[i]); |
2422 | rc = security_context_to_sid(mount_options[i], len, &sid); | 2422 | rc = security_context_to_sid(mount_options[i], len, &sid); |
2423 | if (rc) { | 2423 | if (rc) { |
2424 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 2424 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
2425 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 2425 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
2426 | mount_options[i], sb->s_id, sb->s_type->name, rc); | 2426 | mount_options[i], sb->s_id, sb->s_type->name, rc); |
2427 | goto out_free_opts; | 2427 | goto out_free_opts; |
2428 | } | 2428 | } |
2429 | rc = -EINVAL; | 2429 | rc = -EINVAL; |
2430 | switch (flags[i]) { | 2430 | switch (flags[i]) { |
2431 | case FSCONTEXT_MNT: | 2431 | case FSCONTEXT_MNT: |
2432 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) | 2432 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) |
2433 | goto out_bad_option; | 2433 | goto out_bad_option; |
2434 | break; | 2434 | break; |
2435 | case CONTEXT_MNT: | 2435 | case CONTEXT_MNT: |
2436 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) | 2436 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) |
2437 | goto out_bad_option; | 2437 | goto out_bad_option; |
2438 | break; | 2438 | break; |
2439 | case ROOTCONTEXT_MNT: { | 2439 | case ROOTCONTEXT_MNT: { |
2440 | struct inode_security_struct *root_isec; | 2440 | struct inode_security_struct *root_isec; |
2441 | root_isec = sb->s_root->d_inode->i_security; | 2441 | root_isec = sb->s_root->d_inode->i_security; |
2442 | 2442 | ||
2443 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) | 2443 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) |
2444 | goto out_bad_option; | 2444 | goto out_bad_option; |
2445 | break; | 2445 | break; |
2446 | } | 2446 | } |
2447 | case DEFCONTEXT_MNT: | 2447 | case DEFCONTEXT_MNT: |
2448 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) | 2448 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) |
2449 | goto out_bad_option; | 2449 | goto out_bad_option; |
2450 | break; | 2450 | break; |
2451 | default: | 2451 | default: |
2452 | goto out_free_opts; | 2452 | goto out_free_opts; |
2453 | } | 2453 | } |
2454 | } | 2454 | } |
2455 | 2455 | ||
2456 | rc = 0; | 2456 | rc = 0; |
2457 | out_free_opts: | 2457 | out_free_opts: |
2458 | security_free_mnt_opts(&opts); | 2458 | security_free_mnt_opts(&opts); |
2459 | out_free_secdata: | 2459 | out_free_secdata: |
2460 | free_secdata(secdata); | 2460 | free_secdata(secdata); |
2461 | return rc; | 2461 | return rc; |
2462 | out_bad_option: | 2462 | out_bad_option: |
2463 | printk(KERN_WARNING "SELinux: unable to change security options " | 2463 | printk(KERN_WARNING "SELinux: unable to change security options " |
2464 | "during remount (dev %s, type=%s)\n", sb->s_id, | 2464 | "during remount (dev %s, type=%s)\n", sb->s_id, |
2465 | sb->s_type->name); | 2465 | sb->s_type->name); |
2466 | goto out_free_opts; | 2466 | goto out_free_opts; |
2467 | } | 2467 | } |
2468 | 2468 | ||
2469 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2469 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2470 | { | 2470 | { |
2471 | const struct cred *cred = current_cred(); | 2471 | const struct cred *cred = current_cred(); |
2472 | struct common_audit_data ad; | 2472 | struct common_audit_data ad; |
2473 | int rc; | 2473 | int rc; |
2474 | 2474 | ||
2475 | rc = superblock_doinit(sb, data); | 2475 | rc = superblock_doinit(sb, data); |
2476 | if (rc) | 2476 | if (rc) |
2477 | return rc; | 2477 | return rc; |
2478 | 2478 | ||
2479 | /* Allow all mounts performed by the kernel */ | 2479 | /* Allow all mounts performed by the kernel */ |
2480 | if (flags & MS_KERNMOUNT) | 2480 | if (flags & MS_KERNMOUNT) |
2481 | return 0; | 2481 | return 0; |
2482 | 2482 | ||
2483 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2483 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2484 | ad.u.dentry = sb->s_root; | 2484 | ad.u.dentry = sb->s_root; |
2485 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2485 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2486 | } | 2486 | } |
2487 | 2487 | ||
2488 | static int selinux_sb_statfs(struct dentry *dentry) | 2488 | static int selinux_sb_statfs(struct dentry *dentry) |
2489 | { | 2489 | { |
2490 | const struct cred *cred = current_cred(); | 2490 | const struct cred *cred = current_cred(); |
2491 | struct common_audit_data ad; | 2491 | struct common_audit_data ad; |
2492 | 2492 | ||
2493 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2493 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2494 | ad.u.dentry = dentry->d_sb->s_root; | 2494 | ad.u.dentry = dentry->d_sb->s_root; |
2495 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2495 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2496 | } | 2496 | } |
2497 | 2497 | ||
2498 | static int selinux_mount(char *dev_name, | 2498 | static int selinux_mount(char *dev_name, |
2499 | struct path *path, | 2499 | struct path *path, |
2500 | char *type, | 2500 | char *type, |
2501 | unsigned long flags, | 2501 | unsigned long flags, |
2502 | void *data) | 2502 | void *data) |
2503 | { | 2503 | { |
2504 | const struct cred *cred = current_cred(); | 2504 | const struct cred *cred = current_cred(); |
2505 | 2505 | ||
2506 | if (flags & MS_REMOUNT) | 2506 | if (flags & MS_REMOUNT) |
2507 | return superblock_has_perm(cred, path->mnt->mnt_sb, | 2507 | return superblock_has_perm(cred, path->mnt->mnt_sb, |
2508 | FILESYSTEM__REMOUNT, NULL); | 2508 | FILESYSTEM__REMOUNT, NULL); |
2509 | else | 2509 | else |
2510 | return path_has_perm(cred, path, FILE__MOUNTON); | 2510 | return path_has_perm(cred, path, FILE__MOUNTON); |
2511 | } | 2511 | } |
2512 | 2512 | ||
2513 | static int selinux_umount(struct vfsmount *mnt, int flags) | 2513 | static int selinux_umount(struct vfsmount *mnt, int flags) |
2514 | { | 2514 | { |
2515 | const struct cred *cred = current_cred(); | 2515 | const struct cred *cred = current_cred(); |
2516 | 2516 | ||
2517 | return superblock_has_perm(cred, mnt->mnt_sb, | 2517 | return superblock_has_perm(cred, mnt->mnt_sb, |
2518 | FILESYSTEM__UNMOUNT, NULL); | 2518 | FILESYSTEM__UNMOUNT, NULL); |
2519 | } | 2519 | } |
2520 | 2520 | ||
2521 | /* inode security operations */ | 2521 | /* inode security operations */ |
2522 | 2522 | ||
2523 | static int selinux_inode_alloc_security(struct inode *inode) | 2523 | static int selinux_inode_alloc_security(struct inode *inode) |
2524 | { | 2524 | { |
2525 | return inode_alloc_security(inode); | 2525 | return inode_alloc_security(inode); |
2526 | } | 2526 | } |
2527 | 2527 | ||
2528 | static void selinux_inode_free_security(struct inode *inode) | 2528 | static void selinux_inode_free_security(struct inode *inode) |
2529 | { | 2529 | { |
2530 | inode_free_security(inode); | 2530 | inode_free_security(inode); |
2531 | } | 2531 | } |
2532 | 2532 | ||
2533 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2533 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
2534 | const struct qstr *qstr, char **name, | 2534 | const struct qstr *qstr, char **name, |
2535 | void **value, size_t *len) | 2535 | void **value, size_t *len) |
2536 | { | 2536 | { |
2537 | const struct task_security_struct *tsec = current_security(); | 2537 | const struct task_security_struct *tsec = current_security(); |
2538 | struct inode_security_struct *dsec; | 2538 | struct inode_security_struct *dsec; |
2539 | struct superblock_security_struct *sbsec; | 2539 | struct superblock_security_struct *sbsec; |
2540 | u32 sid, newsid, clen; | 2540 | u32 sid, newsid, clen; |
2541 | int rc; | 2541 | int rc; |
2542 | char *namep = NULL, *context; | 2542 | char *namep = NULL, *context; |
2543 | 2543 | ||
2544 | dsec = dir->i_security; | 2544 | dsec = dir->i_security; |
2545 | sbsec = dir->i_sb->s_security; | 2545 | sbsec = dir->i_sb->s_security; |
2546 | 2546 | ||
2547 | sid = tsec->sid; | 2547 | sid = tsec->sid; |
2548 | newsid = tsec->create_sid; | 2548 | newsid = tsec->create_sid; |
2549 | 2549 | ||
2550 | if ((sbsec->flags & SE_SBINITIALIZED) && | 2550 | if ((sbsec->flags & SE_SBINITIALIZED) && |
2551 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) | 2551 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) |
2552 | newsid = sbsec->mntpoint_sid; | 2552 | newsid = sbsec->mntpoint_sid; |
2553 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 2553 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { |
2554 | rc = security_transition_sid(sid, dsec->sid, | 2554 | rc = security_transition_sid(sid, dsec->sid, |
2555 | inode_mode_to_security_class(inode->i_mode), | 2555 | inode_mode_to_security_class(inode->i_mode), |
2556 | qstr, &newsid); | 2556 | qstr, &newsid); |
2557 | if (rc) { | 2557 | if (rc) { |
2558 | printk(KERN_WARNING "%s: " | 2558 | printk(KERN_WARNING "%s: " |
2559 | "security_transition_sid failed, rc=%d (dev=%s " | 2559 | "security_transition_sid failed, rc=%d (dev=%s " |
2560 | "ino=%ld)\n", | 2560 | "ino=%ld)\n", |
2561 | __func__, | 2561 | __func__, |
2562 | -rc, inode->i_sb->s_id, inode->i_ino); | 2562 | -rc, inode->i_sb->s_id, inode->i_ino); |
2563 | return rc; | 2563 | return rc; |
2564 | } | 2564 | } |
2565 | } | 2565 | } |
2566 | 2566 | ||
2567 | /* Possibly defer initialization to selinux_complete_init. */ | 2567 | /* Possibly defer initialization to selinux_complete_init. */ |
2568 | if (sbsec->flags & SE_SBINITIALIZED) { | 2568 | if (sbsec->flags & SE_SBINITIALIZED) { |
2569 | struct inode_security_struct *isec = inode->i_security; | 2569 | struct inode_security_struct *isec = inode->i_security; |
2570 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 2570 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
2571 | isec->sid = newsid; | 2571 | isec->sid = newsid; |
2572 | isec->initialized = 1; | 2572 | isec->initialized = 1; |
2573 | } | 2573 | } |
2574 | 2574 | ||
2575 | if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) | 2575 | if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) |
2576 | return -EOPNOTSUPP; | 2576 | return -EOPNOTSUPP; |
2577 | 2577 | ||
2578 | if (name) { | 2578 | if (name) { |
2579 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS); | 2579 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS); |
2580 | if (!namep) | 2580 | if (!namep) |
2581 | return -ENOMEM; | 2581 | return -ENOMEM; |
2582 | *name = namep; | 2582 | *name = namep; |
2583 | } | 2583 | } |
2584 | 2584 | ||
2585 | if (value && len) { | 2585 | if (value && len) { |
2586 | rc = security_sid_to_context_force(newsid, &context, &clen); | 2586 | rc = security_sid_to_context_force(newsid, &context, &clen); |
2587 | if (rc) { | 2587 | if (rc) { |
2588 | kfree(namep); | 2588 | kfree(namep); |
2589 | return rc; | 2589 | return rc; |
2590 | } | 2590 | } |
2591 | *value = context; | 2591 | *value = context; |
2592 | *len = clen; | 2592 | *len = clen; |
2593 | } | 2593 | } |
2594 | 2594 | ||
2595 | return 0; | 2595 | return 0; |
2596 | } | 2596 | } |
2597 | 2597 | ||
2598 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) | 2598 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) |
2599 | { | 2599 | { |
2600 | return may_create(dir, dentry, SECCLASS_FILE); | 2600 | return may_create(dir, dentry, SECCLASS_FILE); |
2601 | } | 2601 | } |
2602 | 2602 | ||
2603 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) | 2603 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) |
2604 | { | 2604 | { |
2605 | return may_link(dir, old_dentry, MAY_LINK); | 2605 | return may_link(dir, old_dentry, MAY_LINK); |
2606 | } | 2606 | } |
2607 | 2607 | ||
2608 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) | 2608 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) |
2609 | { | 2609 | { |
2610 | return may_link(dir, dentry, MAY_UNLINK); | 2610 | return may_link(dir, dentry, MAY_UNLINK); |
2611 | } | 2611 | } |
2612 | 2612 | ||
2613 | static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) | 2613 | static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) |
2614 | { | 2614 | { |
2615 | return may_create(dir, dentry, SECCLASS_LNK_FILE); | 2615 | return may_create(dir, dentry, SECCLASS_LNK_FILE); |
2616 | } | 2616 | } |
2617 | 2617 | ||
2618 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) | 2618 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) |
2619 | { | 2619 | { |
2620 | return may_create(dir, dentry, SECCLASS_DIR); | 2620 | return may_create(dir, dentry, SECCLASS_DIR); |
2621 | } | 2621 | } |
2622 | 2622 | ||
2623 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) | 2623 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) |
2624 | { | 2624 | { |
2625 | return may_link(dir, dentry, MAY_RMDIR); | 2625 | return may_link(dir, dentry, MAY_RMDIR); |
2626 | } | 2626 | } |
2627 | 2627 | ||
2628 | static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | 2628 | static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) |
2629 | { | 2629 | { |
2630 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); | 2630 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); |
2631 | } | 2631 | } |
2632 | 2632 | ||
2633 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, | 2633 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, |
2634 | struct inode *new_inode, struct dentry *new_dentry) | 2634 | struct inode *new_inode, struct dentry *new_dentry) |
2635 | { | 2635 | { |
2636 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); | 2636 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); |
2637 | } | 2637 | } |
2638 | 2638 | ||
2639 | static int selinux_inode_readlink(struct dentry *dentry) | 2639 | static int selinux_inode_readlink(struct dentry *dentry) |
2640 | { | 2640 | { |
2641 | const struct cred *cred = current_cred(); | 2641 | const struct cred *cred = current_cred(); |
2642 | 2642 | ||
2643 | return dentry_has_perm(cred, dentry, FILE__READ); | 2643 | return dentry_has_perm(cred, dentry, FILE__READ); |
2644 | } | 2644 | } |
2645 | 2645 | ||
2646 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) | 2646 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) |
2647 | { | 2647 | { |
2648 | const struct cred *cred = current_cred(); | 2648 | const struct cred *cred = current_cred(); |
2649 | 2649 | ||
2650 | return dentry_has_perm(cred, dentry, FILE__READ); | 2650 | return dentry_has_perm(cred, dentry, FILE__READ); |
2651 | } | 2651 | } |
2652 | 2652 | ||
2653 | static int selinux_inode_permission(struct inode *inode, int mask) | 2653 | static int selinux_inode_permission(struct inode *inode, int mask) |
2654 | { | 2654 | { |
2655 | const struct cred *cred = current_cred(); | 2655 | const struct cred *cred = current_cred(); |
2656 | struct common_audit_data ad; | 2656 | struct common_audit_data ad; |
2657 | u32 perms; | 2657 | u32 perms; |
2658 | bool from_access; | 2658 | bool from_access; |
2659 | unsigned flags = mask & MAY_NOT_BLOCK; | 2659 | unsigned flags = mask & MAY_NOT_BLOCK; |
2660 | 2660 | ||
2661 | from_access = mask & MAY_ACCESS; | 2661 | from_access = mask & MAY_ACCESS; |
2662 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); | 2662 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2663 | 2663 | ||
2664 | /* No permission to check. Existence test. */ | 2664 | /* No permission to check. Existence test. */ |
2665 | if (!mask) | 2665 | if (!mask) |
2666 | return 0; | 2666 | return 0; |
2667 | 2667 | ||
2668 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | 2668 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2669 | ad.u.inode = inode; | 2669 | ad.u.inode = inode; |
2670 | 2670 | ||
2671 | if (from_access) | 2671 | if (from_access) |
2672 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | 2672 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; |
2673 | 2673 | ||
2674 | perms = file_mask_to_av(inode->i_mode, mask); | 2674 | perms = file_mask_to_av(inode->i_mode, mask); |
2675 | 2675 | ||
2676 | return inode_has_perm(cred, inode, perms, &ad, flags); | 2676 | return inode_has_perm(cred, inode, perms, &ad, flags); |
2677 | } | 2677 | } |
2678 | 2678 | ||
2679 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2679 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2680 | { | 2680 | { |
2681 | const struct cred *cred = current_cred(); | 2681 | const struct cred *cred = current_cred(); |
2682 | unsigned int ia_valid = iattr->ia_valid; | 2682 | unsigned int ia_valid = iattr->ia_valid; |
2683 | 2683 | ||
2684 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | 2684 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ |
2685 | if (ia_valid & ATTR_FORCE) { | 2685 | if (ia_valid & ATTR_FORCE) { |
2686 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | 2686 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | |
2687 | ATTR_FORCE); | 2687 | ATTR_FORCE); |
2688 | if (!ia_valid) | 2688 | if (!ia_valid) |
2689 | return 0; | 2689 | return 0; |
2690 | } | 2690 | } |
2691 | 2691 | ||
2692 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | 2692 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2693 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 2693 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2694 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | 2694 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2695 | 2695 | ||
2696 | return dentry_has_perm(cred, dentry, FILE__WRITE); | 2696 | return dentry_has_perm(cred, dentry, FILE__WRITE); |
2697 | } | 2697 | } |
2698 | 2698 | ||
2699 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 2699 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
2700 | { | 2700 | { |
2701 | const struct cred *cred = current_cred(); | 2701 | const struct cred *cred = current_cred(); |
2702 | struct path path; | 2702 | struct path path; |
2703 | 2703 | ||
2704 | path.dentry = dentry; | 2704 | path.dentry = dentry; |
2705 | path.mnt = mnt; | 2705 | path.mnt = mnt; |
2706 | 2706 | ||
2707 | return path_has_perm(cred, &path, FILE__GETATTR); | 2707 | return path_has_perm(cred, &path, FILE__GETATTR); |
2708 | } | 2708 | } |
2709 | 2709 | ||
2710 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | 2710 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) |
2711 | { | 2711 | { |
2712 | const struct cred *cred = current_cred(); | 2712 | const struct cred *cred = current_cred(); |
2713 | 2713 | ||
2714 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 2714 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
2715 | sizeof XATTR_SECURITY_PREFIX - 1)) { | 2715 | sizeof XATTR_SECURITY_PREFIX - 1)) { |
2716 | if (!strcmp(name, XATTR_NAME_CAPS)) { | 2716 | if (!strcmp(name, XATTR_NAME_CAPS)) { |
2717 | if (!capable(CAP_SETFCAP)) | 2717 | if (!capable(CAP_SETFCAP)) |
2718 | return -EPERM; | 2718 | return -EPERM; |
2719 | } else if (!capable(CAP_SYS_ADMIN)) { | 2719 | } else if (!capable(CAP_SYS_ADMIN)) { |
2720 | /* A different attribute in the security namespace. | 2720 | /* A different attribute in the security namespace. |
2721 | Restrict to administrator. */ | 2721 | Restrict to administrator. */ |
2722 | return -EPERM; | 2722 | return -EPERM; |
2723 | } | 2723 | } |
2724 | } | 2724 | } |
2725 | 2725 | ||
2726 | /* Not an attribute we recognize, so just check the | 2726 | /* Not an attribute we recognize, so just check the |
2727 | ordinary setattr permission. */ | 2727 | ordinary setattr permission. */ |
2728 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | 2728 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2729 | } | 2729 | } |
2730 | 2730 | ||
2731 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | 2731 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, |
2732 | const void *value, size_t size, int flags) | 2732 | const void *value, size_t size, int flags) |
2733 | { | 2733 | { |
2734 | struct inode *inode = dentry->d_inode; | 2734 | struct inode *inode = dentry->d_inode; |
2735 | struct inode_security_struct *isec = inode->i_security; | 2735 | struct inode_security_struct *isec = inode->i_security; |
2736 | struct superblock_security_struct *sbsec; | 2736 | struct superblock_security_struct *sbsec; |
2737 | struct common_audit_data ad; | 2737 | struct common_audit_data ad; |
2738 | u32 newsid, sid = current_sid(); | 2738 | u32 newsid, sid = current_sid(); |
2739 | int rc = 0; | 2739 | int rc = 0; |
2740 | 2740 | ||
2741 | if (strcmp(name, XATTR_NAME_SELINUX)) | 2741 | if (strcmp(name, XATTR_NAME_SELINUX)) |
2742 | return selinux_inode_setotherxattr(dentry, name); | 2742 | return selinux_inode_setotherxattr(dentry, name); |
2743 | 2743 | ||
2744 | sbsec = inode->i_sb->s_security; | 2744 | sbsec = inode->i_sb->s_security; |
2745 | if (!(sbsec->flags & SE_SBLABELSUPP)) | 2745 | if (!(sbsec->flags & SE_SBLABELSUPP)) |
2746 | return -EOPNOTSUPP; | 2746 | return -EOPNOTSUPP; |
2747 | 2747 | ||
2748 | if (!inode_owner_or_capable(inode)) | 2748 | if (!inode_owner_or_capable(inode)) |
2749 | return -EPERM; | 2749 | return -EPERM; |
2750 | 2750 | ||
2751 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2751 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2752 | ad.u.dentry = dentry; | 2752 | ad.u.dentry = dentry; |
2753 | 2753 | ||
2754 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2754 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
2755 | FILE__RELABELFROM, &ad); | 2755 | FILE__RELABELFROM, &ad); |
2756 | if (rc) | 2756 | if (rc) |
2757 | return rc; | 2757 | return rc; |
2758 | 2758 | ||
2759 | rc = security_context_to_sid(value, size, &newsid); | 2759 | rc = security_context_to_sid(value, size, &newsid); |
2760 | if (rc == -EINVAL) { | 2760 | if (rc == -EINVAL) { |
2761 | if (!capable(CAP_MAC_ADMIN)) | 2761 | if (!capable(CAP_MAC_ADMIN)) |
2762 | return rc; | 2762 | return rc; |
2763 | rc = security_context_to_sid_force(value, size, &newsid); | 2763 | rc = security_context_to_sid_force(value, size, &newsid); |
2764 | } | 2764 | } |
2765 | if (rc) | 2765 | if (rc) |
2766 | return rc; | 2766 | return rc; |
2767 | 2767 | ||
2768 | rc = avc_has_perm(sid, newsid, isec->sclass, | 2768 | rc = avc_has_perm(sid, newsid, isec->sclass, |
2769 | FILE__RELABELTO, &ad); | 2769 | FILE__RELABELTO, &ad); |
2770 | if (rc) | 2770 | if (rc) |
2771 | return rc; | 2771 | return rc; |
2772 | 2772 | ||
2773 | rc = security_validate_transition(isec->sid, newsid, sid, | 2773 | rc = security_validate_transition(isec->sid, newsid, sid, |
2774 | isec->sclass); | 2774 | isec->sclass); |
2775 | if (rc) | 2775 | if (rc) |
2776 | return rc; | 2776 | return rc; |
2777 | 2777 | ||
2778 | return avc_has_perm(newsid, | 2778 | return avc_has_perm(newsid, |
2779 | sbsec->sid, | 2779 | sbsec->sid, |
2780 | SECCLASS_FILESYSTEM, | 2780 | SECCLASS_FILESYSTEM, |
2781 | FILESYSTEM__ASSOCIATE, | 2781 | FILESYSTEM__ASSOCIATE, |
2782 | &ad); | 2782 | &ad); |
2783 | } | 2783 | } |
2784 | 2784 | ||
2785 | static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | 2785 | static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, |
2786 | const void *value, size_t size, | 2786 | const void *value, size_t size, |
2787 | int flags) | 2787 | int flags) |
2788 | { | 2788 | { |
2789 | struct inode *inode = dentry->d_inode; | 2789 | struct inode *inode = dentry->d_inode; |
2790 | struct inode_security_struct *isec = inode->i_security; | 2790 | struct inode_security_struct *isec = inode->i_security; |
2791 | u32 newsid; | 2791 | u32 newsid; |
2792 | int rc; | 2792 | int rc; |
2793 | 2793 | ||
2794 | if (strcmp(name, XATTR_NAME_SELINUX)) { | 2794 | if (strcmp(name, XATTR_NAME_SELINUX)) { |
2795 | /* Not an attribute we recognize, so nothing to do. */ | 2795 | /* Not an attribute we recognize, so nothing to do. */ |
2796 | return; | 2796 | return; |
2797 | } | 2797 | } |
2798 | 2798 | ||
2799 | rc = security_context_to_sid_force(value, size, &newsid); | 2799 | rc = security_context_to_sid_force(value, size, &newsid); |
2800 | if (rc) { | 2800 | if (rc) { |
2801 | printk(KERN_ERR "SELinux: unable to map context to SID" | 2801 | printk(KERN_ERR "SELinux: unable to map context to SID" |
2802 | "for (%s, %lu), rc=%d\n", | 2802 | "for (%s, %lu), rc=%d\n", |
2803 | inode->i_sb->s_id, inode->i_ino, -rc); | 2803 | inode->i_sb->s_id, inode->i_ino, -rc); |
2804 | return; | 2804 | return; |
2805 | } | 2805 | } |
2806 | 2806 | ||
2807 | isec->sid = newsid; | 2807 | isec->sid = newsid; |
2808 | return; | 2808 | return; |
2809 | } | 2809 | } |
2810 | 2810 | ||
2811 | static int selinux_inode_getxattr(struct dentry *dentry, const char *name) | 2811 | static int selinux_inode_getxattr(struct dentry *dentry, const char *name) |
2812 | { | 2812 | { |
2813 | const struct cred *cred = current_cred(); | 2813 | const struct cred *cred = current_cred(); |
2814 | 2814 | ||
2815 | return dentry_has_perm(cred, dentry, FILE__GETATTR); | 2815 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2816 | } | 2816 | } |
2817 | 2817 | ||
2818 | static int selinux_inode_listxattr(struct dentry *dentry) | 2818 | static int selinux_inode_listxattr(struct dentry *dentry) |
2819 | { | 2819 | { |
2820 | const struct cred *cred = current_cred(); | 2820 | const struct cred *cred = current_cred(); |
2821 | 2821 | ||
2822 | return dentry_has_perm(cred, dentry, FILE__GETATTR); | 2822 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2823 | } | 2823 | } |
2824 | 2824 | ||
2825 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | 2825 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) |
2826 | { | 2826 | { |
2827 | if (strcmp(name, XATTR_NAME_SELINUX)) | 2827 | if (strcmp(name, XATTR_NAME_SELINUX)) |
2828 | return selinux_inode_setotherxattr(dentry, name); | 2828 | return selinux_inode_setotherxattr(dentry, name); |
2829 | 2829 | ||
2830 | /* No one is allowed to remove a SELinux security label. | 2830 | /* No one is allowed to remove a SELinux security label. |
2831 | You can change the label, but all data must be labeled. */ | 2831 | You can change the label, but all data must be labeled. */ |
2832 | return -EACCES; | 2832 | return -EACCES; |
2833 | } | 2833 | } |
2834 | 2834 | ||
2835 | /* | 2835 | /* |
2836 | * Copy the inode security context value to the user. | 2836 | * Copy the inode security context value to the user. |
2837 | * | 2837 | * |
2838 | * Permission check is handled by selinux_inode_getxattr hook. | 2838 | * Permission check is handled by selinux_inode_getxattr hook. |
2839 | */ | 2839 | */ |
2840 | static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) | 2840 | static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
2841 | { | 2841 | { |
2842 | u32 size; | 2842 | u32 size; |
2843 | int error; | 2843 | int error; |
2844 | char *context = NULL; | 2844 | char *context = NULL; |
2845 | struct inode_security_struct *isec = inode->i_security; | 2845 | struct inode_security_struct *isec = inode->i_security; |
2846 | 2846 | ||
2847 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 2847 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
2848 | return -EOPNOTSUPP; | 2848 | return -EOPNOTSUPP; |
2849 | 2849 | ||
2850 | /* | 2850 | /* |
2851 | * If the caller has CAP_MAC_ADMIN, then get the raw context | 2851 | * If the caller has CAP_MAC_ADMIN, then get the raw context |
2852 | * value even if it is not defined by current policy; otherwise, | 2852 | * value even if it is not defined by current policy; otherwise, |
2853 | * use the in-core value under current policy. | 2853 | * use the in-core value under current policy. |
2854 | * Use the non-auditing forms of the permission checks since | 2854 | * Use the non-auditing forms of the permission checks since |
2855 | * getxattr may be called by unprivileged processes commonly | 2855 | * getxattr may be called by unprivileged processes commonly |
2856 | * and lack of permission just means that we fall back to the | 2856 | * and lack of permission just means that we fall back to the |
2857 | * in-core context value, not a denial. | 2857 | * in-core context value, not a denial. |
2858 | */ | 2858 | */ |
2859 | error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN, | 2859 | error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN, |
2860 | SECURITY_CAP_NOAUDIT); | 2860 | SECURITY_CAP_NOAUDIT); |
2861 | if (!error) | 2861 | if (!error) |
2862 | error = security_sid_to_context_force(isec->sid, &context, | 2862 | error = security_sid_to_context_force(isec->sid, &context, |
2863 | &size); | 2863 | &size); |
2864 | else | 2864 | else |
2865 | error = security_sid_to_context(isec->sid, &context, &size); | 2865 | error = security_sid_to_context(isec->sid, &context, &size); |
2866 | if (error) | 2866 | if (error) |
2867 | return error; | 2867 | return error; |
2868 | error = size; | 2868 | error = size; |
2869 | if (alloc) { | 2869 | if (alloc) { |
2870 | *buffer = context; | 2870 | *buffer = context; |
2871 | goto out_nofree; | 2871 | goto out_nofree; |
2872 | } | 2872 | } |
2873 | kfree(context); | 2873 | kfree(context); |
2874 | out_nofree: | 2874 | out_nofree: |
2875 | return error; | 2875 | return error; |
2876 | } | 2876 | } |
2877 | 2877 | ||
2878 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 2878 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
2879 | const void *value, size_t size, int flags) | 2879 | const void *value, size_t size, int flags) |
2880 | { | 2880 | { |
2881 | struct inode_security_struct *isec = inode->i_security; | 2881 | struct inode_security_struct *isec = inode->i_security; |
2882 | u32 newsid; | 2882 | u32 newsid; |
2883 | int rc; | 2883 | int rc; |
2884 | 2884 | ||
2885 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 2885 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
2886 | return -EOPNOTSUPP; | 2886 | return -EOPNOTSUPP; |
2887 | 2887 | ||
2888 | if (!value || !size) | 2888 | if (!value || !size) |
2889 | return -EACCES; | 2889 | return -EACCES; |
2890 | 2890 | ||
2891 | rc = security_context_to_sid((void *)value, size, &newsid); | 2891 | rc = security_context_to_sid((void *)value, size, &newsid); |
2892 | if (rc) | 2892 | if (rc) |
2893 | return rc; | 2893 | return rc; |
2894 | 2894 | ||
2895 | isec->sid = newsid; | 2895 | isec->sid = newsid; |
2896 | isec->initialized = 1; | 2896 | isec->initialized = 1; |
2897 | return 0; | 2897 | return 0; |
2898 | } | 2898 | } |
2899 | 2899 | ||
2900 | static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) | 2900 | static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) |
2901 | { | 2901 | { |
2902 | const int len = sizeof(XATTR_NAME_SELINUX); | 2902 | const int len = sizeof(XATTR_NAME_SELINUX); |
2903 | if (buffer && len <= buffer_size) | 2903 | if (buffer && len <= buffer_size) |
2904 | memcpy(buffer, XATTR_NAME_SELINUX, len); | 2904 | memcpy(buffer, XATTR_NAME_SELINUX, len); |
2905 | return len; | 2905 | return len; |
2906 | } | 2906 | } |
2907 | 2907 | ||
2908 | static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) | 2908 | static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) |
2909 | { | 2909 | { |
2910 | struct inode_security_struct *isec = inode->i_security; | 2910 | struct inode_security_struct *isec = inode->i_security; |
2911 | *secid = isec->sid; | 2911 | *secid = isec->sid; |
2912 | } | 2912 | } |
2913 | 2913 | ||
2914 | /* file security operations */ | 2914 | /* file security operations */ |
2915 | 2915 | ||
2916 | static int selinux_revalidate_file_permission(struct file *file, int mask) | 2916 | static int selinux_revalidate_file_permission(struct file *file, int mask) |
2917 | { | 2917 | { |
2918 | const struct cred *cred = current_cred(); | 2918 | const struct cred *cred = current_cred(); |
2919 | struct inode *inode = file->f_path.dentry->d_inode; | 2919 | struct inode *inode = file->f_path.dentry->d_inode; |
2920 | 2920 | ||
2921 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2921 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2922 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2922 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2923 | mask |= MAY_APPEND; | 2923 | mask |= MAY_APPEND; |
2924 | 2924 | ||
2925 | return file_has_perm(cred, file, | 2925 | return file_has_perm(cred, file, |
2926 | file_mask_to_av(inode->i_mode, mask)); | 2926 | file_mask_to_av(inode->i_mode, mask)); |
2927 | } | 2927 | } |
2928 | 2928 | ||
2929 | static int selinux_file_permission(struct file *file, int mask) | 2929 | static int selinux_file_permission(struct file *file, int mask) |
2930 | { | 2930 | { |
2931 | struct inode *inode = file->f_path.dentry->d_inode; | 2931 | struct inode *inode = file->f_path.dentry->d_inode; |
2932 | struct file_security_struct *fsec = file->f_security; | 2932 | struct file_security_struct *fsec = file->f_security; |
2933 | struct inode_security_struct *isec = inode->i_security; | 2933 | struct inode_security_struct *isec = inode->i_security; |
2934 | u32 sid = current_sid(); | 2934 | u32 sid = current_sid(); |
2935 | 2935 | ||
2936 | if (!mask) | 2936 | if (!mask) |
2937 | /* No permission to check. Existence test. */ | 2937 | /* No permission to check. Existence test. */ |
2938 | return 0; | 2938 | return 0; |
2939 | 2939 | ||
2940 | if (sid == fsec->sid && fsec->isid == isec->sid && | 2940 | if (sid == fsec->sid && fsec->isid == isec->sid && |
2941 | fsec->pseqno == avc_policy_seqno()) | 2941 | fsec->pseqno == avc_policy_seqno()) |
2942 | /* No change since dentry_open check. */ | 2942 | /* No change since dentry_open check. */ |
2943 | return 0; | 2943 | return 0; |
2944 | 2944 | ||
2945 | return selinux_revalidate_file_permission(file, mask); | 2945 | return selinux_revalidate_file_permission(file, mask); |
2946 | } | 2946 | } |
2947 | 2947 | ||
2948 | static int selinux_file_alloc_security(struct file *file) | 2948 | static int selinux_file_alloc_security(struct file *file) |
2949 | { | 2949 | { |
2950 | return file_alloc_security(file); | 2950 | return file_alloc_security(file); |
2951 | } | 2951 | } |
2952 | 2952 | ||
2953 | static void selinux_file_free_security(struct file *file) | 2953 | static void selinux_file_free_security(struct file *file) |
2954 | { | 2954 | { |
2955 | file_free_security(file); | 2955 | file_free_security(file); |
2956 | } | 2956 | } |
2957 | 2957 | ||
2958 | static int selinux_file_ioctl(struct file *file, unsigned int cmd, | 2958 | static int selinux_file_ioctl(struct file *file, unsigned int cmd, |
2959 | unsigned long arg) | 2959 | unsigned long arg) |
2960 | { | 2960 | { |
2961 | const struct cred *cred = current_cred(); | 2961 | const struct cred *cred = current_cred(); |
2962 | int error = 0; | 2962 | int error = 0; |
2963 | 2963 | ||
2964 | switch (cmd) { | 2964 | switch (cmd) { |
2965 | case FIONREAD: | 2965 | case FIONREAD: |
2966 | /* fall through */ | 2966 | /* fall through */ |
2967 | case FIBMAP: | 2967 | case FIBMAP: |
2968 | /* fall through */ | 2968 | /* fall through */ |
2969 | case FIGETBSZ: | 2969 | case FIGETBSZ: |
2970 | /* fall through */ | 2970 | /* fall through */ |
2971 | case EXT2_IOC_GETFLAGS: | 2971 | case EXT2_IOC_GETFLAGS: |
2972 | /* fall through */ | 2972 | /* fall through */ |
2973 | case EXT2_IOC_GETVERSION: | 2973 | case EXT2_IOC_GETVERSION: |
2974 | error = file_has_perm(cred, file, FILE__GETATTR); | 2974 | error = file_has_perm(cred, file, FILE__GETATTR); |
2975 | break; | 2975 | break; |
2976 | 2976 | ||
2977 | case EXT2_IOC_SETFLAGS: | 2977 | case EXT2_IOC_SETFLAGS: |
2978 | /* fall through */ | 2978 | /* fall through */ |
2979 | case EXT2_IOC_SETVERSION: | 2979 | case EXT2_IOC_SETVERSION: |
2980 | error = file_has_perm(cred, file, FILE__SETATTR); | 2980 | error = file_has_perm(cred, file, FILE__SETATTR); |
2981 | break; | 2981 | break; |
2982 | 2982 | ||
2983 | /* sys_ioctl() checks */ | 2983 | /* sys_ioctl() checks */ |
2984 | case FIONBIO: | 2984 | case FIONBIO: |
2985 | /* fall through */ | 2985 | /* fall through */ |
2986 | case FIOASYNC: | 2986 | case FIOASYNC: |
2987 | error = file_has_perm(cred, file, 0); | 2987 | error = file_has_perm(cred, file, 0); |
2988 | break; | 2988 | break; |
2989 | 2989 | ||
2990 | case KDSKBENT: | 2990 | case KDSKBENT: |
2991 | case KDSKBSENT: | 2991 | case KDSKBSENT: |
2992 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, | 2992 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, |
2993 | SECURITY_CAP_AUDIT); | 2993 | SECURITY_CAP_AUDIT); |
2994 | break; | 2994 | break; |
2995 | 2995 | ||
2996 | /* default case assumes that the command will go | 2996 | /* default case assumes that the command will go |
2997 | * to the file's ioctl() function. | 2997 | * to the file's ioctl() function. |
2998 | */ | 2998 | */ |
2999 | default: | 2999 | default: |
3000 | error = file_has_perm(cred, file, FILE__IOCTL); | 3000 | error = file_has_perm(cred, file, FILE__IOCTL); |
3001 | } | 3001 | } |
3002 | return error; | 3002 | return error; |
3003 | } | 3003 | } |
3004 | 3004 | ||
3005 | static int default_noexec; | 3005 | static int default_noexec; |
3006 | 3006 | ||
3007 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3007 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
3008 | { | 3008 | { |
3009 | const struct cred *cred = current_cred(); | 3009 | const struct cred *cred = current_cred(); |
3010 | int rc = 0; | 3010 | int rc = 0; |
3011 | 3011 | ||
3012 | if (default_noexec && | 3012 | if (default_noexec && |
3013 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 3013 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
3014 | /* | 3014 | /* |
3015 | * We are making executable an anonymous mapping or a | 3015 | * We are making executable an anonymous mapping or a |
3016 | * private file mapping that will also be writable. | 3016 | * private file mapping that will also be writable. |
3017 | * This has an additional check. | 3017 | * This has an additional check. |
3018 | */ | 3018 | */ |
3019 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); | 3019 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); |
3020 | if (rc) | 3020 | if (rc) |
3021 | goto error; | 3021 | goto error; |
3022 | } | 3022 | } |
3023 | 3023 | ||
3024 | if (file) { | 3024 | if (file) { |
3025 | /* read access is always possible with a mapping */ | 3025 | /* read access is always possible with a mapping */ |
3026 | u32 av = FILE__READ; | 3026 | u32 av = FILE__READ; |
3027 | 3027 | ||
3028 | /* write access only matters if the mapping is shared */ | 3028 | /* write access only matters if the mapping is shared */ |
3029 | if (shared && (prot & PROT_WRITE)) | 3029 | if (shared && (prot & PROT_WRITE)) |
3030 | av |= FILE__WRITE; | 3030 | av |= FILE__WRITE; |
3031 | 3031 | ||
3032 | if (prot & PROT_EXEC) | 3032 | if (prot & PROT_EXEC) |
3033 | av |= FILE__EXECUTE; | 3033 | av |= FILE__EXECUTE; |
3034 | 3034 | ||
3035 | return file_has_perm(cred, file, av); | 3035 | return file_has_perm(cred, file, av); |
3036 | } | 3036 | } |
3037 | 3037 | ||
3038 | error: | 3038 | error: |
3039 | return rc; | 3039 | return rc; |
3040 | } | 3040 | } |
3041 | 3041 | ||
3042 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3042 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, |
3043 | unsigned long prot, unsigned long flags, | 3043 | unsigned long prot, unsigned long flags, |
3044 | unsigned long addr, unsigned long addr_only) | 3044 | unsigned long addr, unsigned long addr_only) |
3045 | { | 3045 | { |
3046 | int rc = 0; | 3046 | int rc = 0; |
3047 | u32 sid = current_sid(); | 3047 | u32 sid = current_sid(); |
3048 | 3048 | ||
3049 | /* | 3049 | /* |
3050 | * notice that we are intentionally putting the SELinux check before | 3050 | * notice that we are intentionally putting the SELinux check before |
3051 | * the secondary cap_file_mmap check. This is such a likely attempt | 3051 | * the secondary cap_file_mmap check. This is such a likely attempt |
3052 | * at bad behaviour/exploit that we always want to get the AVC, even | 3052 | * at bad behaviour/exploit that we always want to get the AVC, even |
3053 | * if DAC would have also denied the operation. | 3053 | * if DAC would have also denied the operation. |
3054 | */ | 3054 | */ |
3055 | if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { | 3055 | if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { |
3056 | rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, | 3056 | rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, |
3057 | MEMPROTECT__MMAP_ZERO, NULL); | 3057 | MEMPROTECT__MMAP_ZERO, NULL); |
3058 | if (rc) | 3058 | if (rc) |
3059 | return rc; | 3059 | return rc; |
3060 | } | 3060 | } |
3061 | 3061 | ||
3062 | /* do DAC check on address space usage */ | 3062 | /* do DAC check on address space usage */ |
3063 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 3063 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); |
3064 | if (rc || addr_only) | 3064 | if (rc || addr_only) |
3065 | return rc; | 3065 | return rc; |
3066 | 3066 | ||
3067 | if (selinux_checkreqprot) | 3067 | if (selinux_checkreqprot) |
3068 | prot = reqprot; | 3068 | prot = reqprot; |
3069 | 3069 | ||
3070 | return file_map_prot_check(file, prot, | 3070 | return file_map_prot_check(file, prot, |
3071 | (flags & MAP_TYPE) == MAP_SHARED); | 3071 | (flags & MAP_TYPE) == MAP_SHARED); |
3072 | } | 3072 | } |
3073 | 3073 | ||
3074 | static int selinux_file_mprotect(struct vm_area_struct *vma, | 3074 | static int selinux_file_mprotect(struct vm_area_struct *vma, |
3075 | unsigned long reqprot, | 3075 | unsigned long reqprot, |
3076 | unsigned long prot) | 3076 | unsigned long prot) |
3077 | { | 3077 | { |
3078 | const struct cred *cred = current_cred(); | 3078 | const struct cred *cred = current_cred(); |
3079 | 3079 | ||
3080 | if (selinux_checkreqprot) | 3080 | if (selinux_checkreqprot) |
3081 | prot = reqprot; | 3081 | prot = reqprot; |
3082 | 3082 | ||
3083 | if (default_noexec && | 3083 | if (default_noexec && |
3084 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3084 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
3085 | int rc = 0; | 3085 | int rc = 0; |
3086 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3086 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3087 | vma->vm_end <= vma->vm_mm->brk) { | 3087 | vma->vm_end <= vma->vm_mm->brk) { |
3088 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); | 3088 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); |
3089 | } else if (!vma->vm_file && | 3089 | } else if (!vma->vm_file && |
3090 | vma->vm_start <= vma->vm_mm->start_stack && | 3090 | vma->vm_start <= vma->vm_mm->start_stack && |
3091 | vma->vm_end >= vma->vm_mm->start_stack) { | 3091 | vma->vm_end >= vma->vm_mm->start_stack) { |
3092 | rc = current_has_perm(current, PROCESS__EXECSTACK); | 3092 | rc = current_has_perm(current, PROCESS__EXECSTACK); |
3093 | } else if (vma->vm_file && vma->anon_vma) { | 3093 | } else if (vma->vm_file && vma->anon_vma) { |
3094 | /* | 3094 | /* |
3095 | * We are making executable a file mapping that has | 3095 | * We are making executable a file mapping that has |
3096 | * had some COW done. Since pages might have been | 3096 | * had some COW done. Since pages might have been |
3097 | * written, check ability to execute the possibly | 3097 | * written, check ability to execute the possibly |
3098 | * modified content. This typically should only | 3098 | * modified content. This typically should only |
3099 | * occur for text relocations. | 3099 | * occur for text relocations. |
3100 | */ | 3100 | */ |
3101 | rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD); | 3101 | rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD); |
3102 | } | 3102 | } |
3103 | if (rc) | 3103 | if (rc) |
3104 | return rc; | 3104 | return rc; |
3105 | } | 3105 | } |
3106 | 3106 | ||
3107 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3107 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
3108 | } | 3108 | } |
3109 | 3109 | ||
3110 | static int selinux_file_lock(struct file *file, unsigned int cmd) | 3110 | static int selinux_file_lock(struct file *file, unsigned int cmd) |
3111 | { | 3111 | { |
3112 | const struct cred *cred = current_cred(); | 3112 | const struct cred *cred = current_cred(); |
3113 | 3113 | ||
3114 | return file_has_perm(cred, file, FILE__LOCK); | 3114 | return file_has_perm(cred, file, FILE__LOCK); |
3115 | } | 3115 | } |
3116 | 3116 | ||
3117 | static int selinux_file_fcntl(struct file *file, unsigned int cmd, | 3117 | static int selinux_file_fcntl(struct file *file, unsigned int cmd, |
3118 | unsigned long arg) | 3118 | unsigned long arg) |
3119 | { | 3119 | { |
3120 | const struct cred *cred = current_cred(); | 3120 | const struct cred *cred = current_cred(); |
3121 | int err = 0; | 3121 | int err = 0; |
3122 | 3122 | ||
3123 | switch (cmd) { | 3123 | switch (cmd) { |
3124 | case F_SETFL: | 3124 | case F_SETFL: |
3125 | if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { | 3125 | if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { |
3126 | err = -EINVAL; | 3126 | err = -EINVAL; |
3127 | break; | 3127 | break; |
3128 | } | 3128 | } |
3129 | 3129 | ||
3130 | if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) { | 3130 | if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) { |
3131 | err = file_has_perm(cred, file, FILE__WRITE); | 3131 | err = file_has_perm(cred, file, FILE__WRITE); |
3132 | break; | 3132 | break; |
3133 | } | 3133 | } |
3134 | /* fall through */ | 3134 | /* fall through */ |
3135 | case F_SETOWN: | 3135 | case F_SETOWN: |
3136 | case F_SETSIG: | 3136 | case F_SETSIG: |
3137 | case F_GETFL: | 3137 | case F_GETFL: |
3138 | case F_GETOWN: | 3138 | case F_GETOWN: |
3139 | case F_GETSIG: | 3139 | case F_GETSIG: |
3140 | /* Just check FD__USE permission */ | 3140 | /* Just check FD__USE permission */ |
3141 | err = file_has_perm(cred, file, 0); | 3141 | err = file_has_perm(cred, file, 0); |
3142 | break; | 3142 | break; |
3143 | case F_GETLK: | 3143 | case F_GETLK: |
3144 | case F_SETLK: | 3144 | case F_SETLK: |
3145 | case F_SETLKW: | 3145 | case F_SETLKW: |
3146 | #if BITS_PER_LONG == 32 | 3146 | #if BITS_PER_LONG == 32 |
3147 | case F_GETLK64: | 3147 | case F_GETLK64: |
3148 | case F_SETLK64: | 3148 | case F_SETLK64: |
3149 | case F_SETLKW64: | 3149 | case F_SETLKW64: |
3150 | #endif | 3150 | #endif |
3151 | if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { | 3151 | if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { |
3152 | err = -EINVAL; | 3152 | err = -EINVAL; |
3153 | break; | 3153 | break; |
3154 | } | 3154 | } |
3155 | err = file_has_perm(cred, file, FILE__LOCK); | 3155 | err = file_has_perm(cred, file, FILE__LOCK); |
3156 | break; | 3156 | break; |
3157 | } | 3157 | } |
3158 | 3158 | ||
3159 | return err; | 3159 | return err; |
3160 | } | 3160 | } |
3161 | 3161 | ||
3162 | static int selinux_file_set_fowner(struct file *file) | 3162 | static int selinux_file_set_fowner(struct file *file) |
3163 | { | 3163 | { |
3164 | struct file_security_struct *fsec; | 3164 | struct file_security_struct *fsec; |
3165 | 3165 | ||
3166 | fsec = file->f_security; | 3166 | fsec = file->f_security; |
3167 | fsec->fown_sid = current_sid(); | 3167 | fsec->fown_sid = current_sid(); |
3168 | 3168 | ||
3169 | return 0; | 3169 | return 0; |
3170 | } | 3170 | } |
3171 | 3171 | ||
3172 | static int selinux_file_send_sigiotask(struct task_struct *tsk, | 3172 | static int selinux_file_send_sigiotask(struct task_struct *tsk, |
3173 | struct fown_struct *fown, int signum) | 3173 | struct fown_struct *fown, int signum) |
3174 | { | 3174 | { |
3175 | struct file *file; | 3175 | struct file *file; |
3176 | u32 sid = task_sid(tsk); | 3176 | u32 sid = task_sid(tsk); |
3177 | u32 perm; | 3177 | u32 perm; |
3178 | struct file_security_struct *fsec; | 3178 | struct file_security_struct *fsec; |
3179 | 3179 | ||
3180 | /* struct fown_struct is never outside the context of a struct file */ | 3180 | /* struct fown_struct is never outside the context of a struct file */ |
3181 | file = container_of(fown, struct file, f_owner); | 3181 | file = container_of(fown, struct file, f_owner); |
3182 | 3182 | ||
3183 | fsec = file->f_security; | 3183 | fsec = file->f_security; |
3184 | 3184 | ||
3185 | if (!signum) | 3185 | if (!signum) |
3186 | perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */ | 3186 | perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */ |
3187 | else | 3187 | else |
3188 | perm = signal_to_av(signum); | 3188 | perm = signal_to_av(signum); |
3189 | 3189 | ||
3190 | return avc_has_perm(fsec->fown_sid, sid, | 3190 | return avc_has_perm(fsec->fown_sid, sid, |
3191 | SECCLASS_PROCESS, perm, NULL); | 3191 | SECCLASS_PROCESS, perm, NULL); |
3192 | } | 3192 | } |
3193 | 3193 | ||
3194 | static int selinux_file_receive(struct file *file) | 3194 | static int selinux_file_receive(struct file *file) |
3195 | { | 3195 | { |
3196 | const struct cred *cred = current_cred(); | 3196 | const struct cred *cred = current_cred(); |
3197 | 3197 | ||
3198 | return file_has_perm(cred, file, file_to_av(file)); | 3198 | return file_has_perm(cred, file, file_to_av(file)); |
3199 | } | 3199 | } |
3200 | 3200 | ||
3201 | static int selinux_dentry_open(struct file *file, const struct cred *cred) | 3201 | static int selinux_dentry_open(struct file *file, const struct cred *cred) |
3202 | { | 3202 | { |
3203 | struct file_security_struct *fsec; | 3203 | struct file_security_struct *fsec; |
3204 | struct inode *inode; | 3204 | struct inode *inode; |
3205 | struct inode_security_struct *isec; | 3205 | struct inode_security_struct *isec; |
3206 | 3206 | ||
3207 | inode = file->f_path.dentry->d_inode; | 3207 | inode = file->f_path.dentry->d_inode; |
3208 | fsec = file->f_security; | 3208 | fsec = file->f_security; |
3209 | isec = inode->i_security; | 3209 | isec = inode->i_security; |
3210 | /* | 3210 | /* |
3211 | * Save inode label and policy sequence number | 3211 | * Save inode label and policy sequence number |
3212 | * at open-time so that selinux_file_permission | 3212 | * at open-time so that selinux_file_permission |
3213 | * can determine whether revalidation is necessary. | 3213 | * can determine whether revalidation is necessary. |
3214 | * Task label is already saved in the file security | 3214 | * Task label is already saved in the file security |
3215 | * struct as its SID. | 3215 | * struct as its SID. |
3216 | */ | 3216 | */ |
3217 | fsec->isid = isec->sid; | 3217 | fsec->isid = isec->sid; |
3218 | fsec->pseqno = avc_policy_seqno(); | 3218 | fsec->pseqno = avc_policy_seqno(); |
3219 | /* | 3219 | /* |
3220 | * Since the inode label or policy seqno may have changed | 3220 | * Since the inode label or policy seqno may have changed |
3221 | * between the selinux_inode_permission check and the saving | 3221 | * between the selinux_inode_permission check and the saving |
3222 | * of state above, recheck that access is still permitted. | 3222 | * of state above, recheck that access is still permitted. |
3223 | * Otherwise, access might never be revalidated against the | 3223 | * Otherwise, access might never be revalidated against the |
3224 | * new inode label or new policy. | 3224 | * new inode label or new policy. |
3225 | * This check is not redundant - do not remove. | 3225 | * This check is not redundant - do not remove. |
3226 | */ | 3226 | */ |
3227 | return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); | 3227 | return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); |
3228 | } | 3228 | } |
3229 | 3229 | ||
3230 | /* task security operations */ | 3230 | /* task security operations */ |
3231 | 3231 | ||
3232 | static int selinux_task_create(unsigned long clone_flags) | 3232 | static int selinux_task_create(unsigned long clone_flags) |
3233 | { | 3233 | { |
3234 | return current_has_perm(current, PROCESS__FORK); | 3234 | return current_has_perm(current, PROCESS__FORK); |
3235 | } | 3235 | } |
3236 | 3236 | ||
3237 | /* | 3237 | /* |
3238 | * allocate the SELinux part of blank credentials | 3238 | * allocate the SELinux part of blank credentials |
3239 | */ | 3239 | */ |
3240 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 3240 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
3241 | { | 3241 | { |
3242 | struct task_security_struct *tsec; | 3242 | struct task_security_struct *tsec; |
3243 | 3243 | ||
3244 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | 3244 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); |
3245 | if (!tsec) | 3245 | if (!tsec) |
3246 | return -ENOMEM; | 3246 | return -ENOMEM; |
3247 | 3247 | ||
3248 | cred->security = tsec; | 3248 | cred->security = tsec; |
3249 | return 0; | 3249 | return 0; |
3250 | } | 3250 | } |
3251 | 3251 | ||
3252 | /* | 3252 | /* |
3253 | * detach and free the LSM part of a set of credentials | 3253 | * detach and free the LSM part of a set of credentials |
3254 | */ | 3254 | */ |
3255 | static void selinux_cred_free(struct cred *cred) | 3255 | static void selinux_cred_free(struct cred *cred) |
3256 | { | 3256 | { |
3257 | struct task_security_struct *tsec = cred->security; | 3257 | struct task_security_struct *tsec = cred->security; |
3258 | 3258 | ||
3259 | /* | 3259 | /* |
3260 | * cred->security == NULL if security_cred_alloc_blank() or | 3260 | * cred->security == NULL if security_cred_alloc_blank() or |
3261 | * security_prepare_creds() returned an error. | 3261 | * security_prepare_creds() returned an error. |
3262 | */ | 3262 | */ |
3263 | BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); | 3263 | BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); |
3264 | cred->security = (void *) 0x7UL; | 3264 | cred->security = (void *) 0x7UL; |
3265 | kfree(tsec); | 3265 | kfree(tsec); |
3266 | } | 3266 | } |
3267 | 3267 | ||
3268 | /* | 3268 | /* |
3269 | * prepare a new set of credentials for modification | 3269 | * prepare a new set of credentials for modification |
3270 | */ | 3270 | */ |
3271 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, | 3271 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, |
3272 | gfp_t gfp) | 3272 | gfp_t gfp) |
3273 | { | 3273 | { |
3274 | const struct task_security_struct *old_tsec; | 3274 | const struct task_security_struct *old_tsec; |
3275 | struct task_security_struct *tsec; | 3275 | struct task_security_struct *tsec; |
3276 | 3276 | ||
3277 | old_tsec = old->security; | 3277 | old_tsec = old->security; |
3278 | 3278 | ||
3279 | tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); | 3279 | tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); |
3280 | if (!tsec) | 3280 | if (!tsec) |
3281 | return -ENOMEM; | 3281 | return -ENOMEM; |
3282 | 3282 | ||
3283 | new->security = tsec; | 3283 | new->security = tsec; |
3284 | return 0; | 3284 | return 0; |
3285 | } | 3285 | } |
3286 | 3286 | ||
3287 | /* | 3287 | /* |
3288 | * transfer the SELinux data to a blank set of creds | 3288 | * transfer the SELinux data to a blank set of creds |
3289 | */ | 3289 | */ |
3290 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | 3290 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) |
3291 | { | 3291 | { |
3292 | const struct task_security_struct *old_tsec = old->security; | 3292 | const struct task_security_struct *old_tsec = old->security; |
3293 | struct task_security_struct *tsec = new->security; | 3293 | struct task_security_struct *tsec = new->security; |
3294 | 3294 | ||
3295 | *tsec = *old_tsec; | 3295 | *tsec = *old_tsec; |
3296 | } | 3296 | } |
3297 | 3297 | ||
3298 | /* | 3298 | /* |
3299 | * set the security data for a kernel service | 3299 | * set the security data for a kernel service |
3300 | * - all the creation contexts are set to unlabelled | 3300 | * - all the creation contexts are set to unlabelled |
3301 | */ | 3301 | */ |
3302 | static int selinux_kernel_act_as(struct cred *new, u32 secid) | 3302 | static int selinux_kernel_act_as(struct cred *new, u32 secid) |
3303 | { | 3303 | { |
3304 | struct task_security_struct *tsec = new->security; | 3304 | struct task_security_struct *tsec = new->security; |
3305 | u32 sid = current_sid(); | 3305 | u32 sid = current_sid(); |
3306 | int ret; | 3306 | int ret; |
3307 | 3307 | ||
3308 | ret = avc_has_perm(sid, secid, | 3308 | ret = avc_has_perm(sid, secid, |
3309 | SECCLASS_KERNEL_SERVICE, | 3309 | SECCLASS_KERNEL_SERVICE, |
3310 | KERNEL_SERVICE__USE_AS_OVERRIDE, | 3310 | KERNEL_SERVICE__USE_AS_OVERRIDE, |
3311 | NULL); | 3311 | NULL); |
3312 | if (ret == 0) { | 3312 | if (ret == 0) { |
3313 | tsec->sid = secid; | 3313 | tsec->sid = secid; |
3314 | tsec->create_sid = 0; | 3314 | tsec->create_sid = 0; |
3315 | tsec->keycreate_sid = 0; | 3315 | tsec->keycreate_sid = 0; |
3316 | tsec->sockcreate_sid = 0; | 3316 | tsec->sockcreate_sid = 0; |
3317 | } | 3317 | } |
3318 | return ret; | 3318 | return ret; |
3319 | } | 3319 | } |
3320 | 3320 | ||
3321 | /* | 3321 | /* |
3322 | * set the file creation context in a security record to the same as the | 3322 | * set the file creation context in a security record to the same as the |
3323 | * objective context of the specified inode | 3323 | * objective context of the specified inode |
3324 | */ | 3324 | */ |
3325 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | 3325 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) |
3326 | { | 3326 | { |
3327 | struct inode_security_struct *isec = inode->i_security; | 3327 | struct inode_security_struct *isec = inode->i_security; |
3328 | struct task_security_struct *tsec = new->security; | 3328 | struct task_security_struct *tsec = new->security; |
3329 | u32 sid = current_sid(); | 3329 | u32 sid = current_sid(); |
3330 | int ret; | 3330 | int ret; |
3331 | 3331 | ||
3332 | ret = avc_has_perm(sid, isec->sid, | 3332 | ret = avc_has_perm(sid, isec->sid, |
3333 | SECCLASS_KERNEL_SERVICE, | 3333 | SECCLASS_KERNEL_SERVICE, |
3334 | KERNEL_SERVICE__CREATE_FILES_AS, | 3334 | KERNEL_SERVICE__CREATE_FILES_AS, |
3335 | NULL); | 3335 | NULL); |
3336 | 3336 | ||
3337 | if (ret == 0) | 3337 | if (ret == 0) |
3338 | tsec->create_sid = isec->sid; | 3338 | tsec->create_sid = isec->sid; |
3339 | return ret; | 3339 | return ret; |
3340 | } | 3340 | } |
3341 | 3341 | ||
3342 | static int selinux_kernel_module_request(char *kmod_name) | 3342 | static int selinux_kernel_module_request(char *kmod_name) |
3343 | { | 3343 | { |
3344 | u32 sid; | 3344 | u32 sid; |
3345 | struct common_audit_data ad; | 3345 | struct common_audit_data ad; |
3346 | 3346 | ||
3347 | sid = task_sid(current); | 3347 | sid = task_sid(current); |
3348 | 3348 | ||
3349 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | 3349 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); |
3350 | ad.u.kmod_name = kmod_name; | 3350 | ad.u.kmod_name = kmod_name; |
3351 | 3351 | ||
3352 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | 3352 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, |
3353 | SYSTEM__MODULE_REQUEST, &ad); | 3353 | SYSTEM__MODULE_REQUEST, &ad); |
3354 | } | 3354 | } |
3355 | 3355 | ||
3356 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3356 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3357 | { | 3357 | { |
3358 | return current_has_perm(p, PROCESS__SETPGID); | 3358 | return current_has_perm(p, PROCESS__SETPGID); |
3359 | } | 3359 | } |
3360 | 3360 | ||
3361 | static int selinux_task_getpgid(struct task_struct *p) | 3361 | static int selinux_task_getpgid(struct task_struct *p) |
3362 | { | 3362 | { |
3363 | return current_has_perm(p, PROCESS__GETPGID); | 3363 | return current_has_perm(p, PROCESS__GETPGID); |
3364 | } | 3364 | } |
3365 | 3365 | ||
3366 | static int selinux_task_getsid(struct task_struct *p) | 3366 | static int selinux_task_getsid(struct task_struct *p) |
3367 | { | 3367 | { |
3368 | return current_has_perm(p, PROCESS__GETSESSION); | 3368 | return current_has_perm(p, PROCESS__GETSESSION); |
3369 | } | 3369 | } |
3370 | 3370 | ||
3371 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | 3371 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) |
3372 | { | 3372 | { |
3373 | *secid = task_sid(p); | 3373 | *secid = task_sid(p); |
3374 | } | 3374 | } |
3375 | 3375 | ||
3376 | static int selinux_task_setnice(struct task_struct *p, int nice) | 3376 | static int selinux_task_setnice(struct task_struct *p, int nice) |
3377 | { | 3377 | { |
3378 | int rc; | 3378 | int rc; |
3379 | 3379 | ||
3380 | rc = cap_task_setnice(p, nice); | 3380 | rc = cap_task_setnice(p, nice); |
3381 | if (rc) | 3381 | if (rc) |
3382 | return rc; | 3382 | return rc; |
3383 | 3383 | ||
3384 | return current_has_perm(p, PROCESS__SETSCHED); | 3384 | return current_has_perm(p, PROCESS__SETSCHED); |
3385 | } | 3385 | } |
3386 | 3386 | ||
3387 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 3387 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) |
3388 | { | 3388 | { |
3389 | int rc; | 3389 | int rc; |
3390 | 3390 | ||
3391 | rc = cap_task_setioprio(p, ioprio); | 3391 | rc = cap_task_setioprio(p, ioprio); |
3392 | if (rc) | 3392 | if (rc) |
3393 | return rc; | 3393 | return rc; |
3394 | 3394 | ||
3395 | return current_has_perm(p, PROCESS__SETSCHED); | 3395 | return current_has_perm(p, PROCESS__SETSCHED); |
3396 | } | 3396 | } |
3397 | 3397 | ||
3398 | static int selinux_task_getioprio(struct task_struct *p) | 3398 | static int selinux_task_getioprio(struct task_struct *p) |
3399 | { | 3399 | { |
3400 | return current_has_perm(p, PROCESS__GETSCHED); | 3400 | return current_has_perm(p, PROCESS__GETSCHED); |
3401 | } | 3401 | } |
3402 | 3402 | ||
3403 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | 3403 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
3404 | struct rlimit *new_rlim) | 3404 | struct rlimit *new_rlim) |
3405 | { | 3405 | { |
3406 | struct rlimit *old_rlim = p->signal->rlim + resource; | 3406 | struct rlimit *old_rlim = p->signal->rlim + resource; |
3407 | 3407 | ||
3408 | /* Control the ability to change the hard limit (whether | 3408 | /* Control the ability to change the hard limit (whether |
3409 | lowering or raising it), so that the hard limit can | 3409 | lowering or raising it), so that the hard limit can |
3410 | later be used as a safe reset point for the soft limit | 3410 | later be used as a safe reset point for the soft limit |
3411 | upon context transitions. See selinux_bprm_committing_creds. */ | 3411 | upon context transitions. See selinux_bprm_committing_creds. */ |
3412 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3412 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3413 | return current_has_perm(p, PROCESS__SETRLIMIT); | 3413 | return current_has_perm(p, PROCESS__SETRLIMIT); |
3414 | 3414 | ||
3415 | return 0; | 3415 | return 0; |
3416 | } | 3416 | } |
3417 | 3417 | ||
3418 | static int selinux_task_setscheduler(struct task_struct *p) | 3418 | static int selinux_task_setscheduler(struct task_struct *p) |
3419 | { | 3419 | { |
3420 | int rc; | 3420 | int rc; |
3421 | 3421 | ||
3422 | rc = cap_task_setscheduler(p); | 3422 | rc = cap_task_setscheduler(p); |
3423 | if (rc) | 3423 | if (rc) |
3424 | return rc; | 3424 | return rc; |
3425 | 3425 | ||
3426 | return current_has_perm(p, PROCESS__SETSCHED); | 3426 | return current_has_perm(p, PROCESS__SETSCHED); |
3427 | } | 3427 | } |
3428 | 3428 | ||
3429 | static int selinux_task_getscheduler(struct task_struct *p) | 3429 | static int selinux_task_getscheduler(struct task_struct *p) |
3430 | { | 3430 | { |
3431 | return current_has_perm(p, PROCESS__GETSCHED); | 3431 | return current_has_perm(p, PROCESS__GETSCHED); |
3432 | } | 3432 | } |
3433 | 3433 | ||
3434 | static int selinux_task_movememory(struct task_struct *p) | 3434 | static int selinux_task_movememory(struct task_struct *p) |
3435 | { | 3435 | { |
3436 | return current_has_perm(p, PROCESS__SETSCHED); | 3436 | return current_has_perm(p, PROCESS__SETSCHED); |
3437 | } | 3437 | } |
3438 | 3438 | ||
3439 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, | 3439 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, |
3440 | int sig, u32 secid) | 3440 | int sig, u32 secid) |
3441 | { | 3441 | { |
3442 | u32 perm; | 3442 | u32 perm; |
3443 | int rc; | 3443 | int rc; |
3444 | 3444 | ||
3445 | if (!sig) | 3445 | if (!sig) |
3446 | perm = PROCESS__SIGNULL; /* null signal; existence test */ | 3446 | perm = PROCESS__SIGNULL; /* null signal; existence test */ |
3447 | else | 3447 | else |
3448 | perm = signal_to_av(sig); | 3448 | perm = signal_to_av(sig); |
3449 | if (secid) | 3449 | if (secid) |
3450 | rc = avc_has_perm(secid, task_sid(p), | 3450 | rc = avc_has_perm(secid, task_sid(p), |
3451 | SECCLASS_PROCESS, perm, NULL); | 3451 | SECCLASS_PROCESS, perm, NULL); |
3452 | else | 3452 | else |
3453 | rc = current_has_perm(p, perm); | 3453 | rc = current_has_perm(p, perm); |
3454 | return rc; | 3454 | return rc; |
3455 | } | 3455 | } |
3456 | 3456 | ||
3457 | static int selinux_task_wait(struct task_struct *p) | 3457 | static int selinux_task_wait(struct task_struct *p) |
3458 | { | 3458 | { |
3459 | return task_has_perm(p, current, PROCESS__SIGCHLD); | 3459 | return task_has_perm(p, current, PROCESS__SIGCHLD); |
3460 | } | 3460 | } |
3461 | 3461 | ||
3462 | static void selinux_task_to_inode(struct task_struct *p, | 3462 | static void selinux_task_to_inode(struct task_struct *p, |
3463 | struct inode *inode) | 3463 | struct inode *inode) |
3464 | { | 3464 | { |
3465 | struct inode_security_struct *isec = inode->i_security; | 3465 | struct inode_security_struct *isec = inode->i_security; |
3466 | u32 sid = task_sid(p); | 3466 | u32 sid = task_sid(p); |
3467 | 3467 | ||
3468 | isec->sid = sid; | 3468 | isec->sid = sid; |
3469 | isec->initialized = 1; | 3469 | isec->initialized = 1; |
3470 | } | 3470 | } |
3471 | 3471 | ||
3472 | /* Returns error only if unable to parse addresses */ | 3472 | /* Returns error only if unable to parse addresses */ |
3473 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3473 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3474 | struct common_audit_data *ad, u8 *proto) | 3474 | struct common_audit_data *ad, u8 *proto) |
3475 | { | 3475 | { |
3476 | int offset, ihlen, ret = -EINVAL; | 3476 | int offset, ihlen, ret = -EINVAL; |
3477 | struct iphdr _iph, *ih; | 3477 | struct iphdr _iph, *ih; |
3478 | 3478 | ||
3479 | offset = skb_network_offset(skb); | 3479 | offset = skb_network_offset(skb); |
3480 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | 3480 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); |
3481 | if (ih == NULL) | 3481 | if (ih == NULL) |
3482 | goto out; | 3482 | goto out; |
3483 | 3483 | ||
3484 | ihlen = ih->ihl * 4; | 3484 | ihlen = ih->ihl * 4; |
3485 | if (ihlen < sizeof(_iph)) | 3485 | if (ihlen < sizeof(_iph)) |
3486 | goto out; | 3486 | goto out; |
3487 | 3487 | ||
3488 | ad->u.net.v4info.saddr = ih->saddr; | 3488 | ad->u.net.v4info.saddr = ih->saddr; |
3489 | ad->u.net.v4info.daddr = ih->daddr; | 3489 | ad->u.net.v4info.daddr = ih->daddr; |
3490 | ret = 0; | 3490 | ret = 0; |
3491 | 3491 | ||
3492 | if (proto) | 3492 | if (proto) |
3493 | *proto = ih->protocol; | 3493 | *proto = ih->protocol; |
3494 | 3494 | ||
3495 | switch (ih->protocol) { | 3495 | switch (ih->protocol) { |
3496 | case IPPROTO_TCP: { | 3496 | case IPPROTO_TCP: { |
3497 | struct tcphdr _tcph, *th; | 3497 | struct tcphdr _tcph, *th; |
3498 | 3498 | ||
3499 | if (ntohs(ih->frag_off) & IP_OFFSET) | 3499 | if (ntohs(ih->frag_off) & IP_OFFSET) |
3500 | break; | 3500 | break; |
3501 | 3501 | ||
3502 | offset += ihlen; | 3502 | offset += ihlen; |
3503 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); | 3503 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); |
3504 | if (th == NULL) | 3504 | if (th == NULL) |
3505 | break; | 3505 | break; |
3506 | 3506 | ||
3507 | ad->u.net.sport = th->source; | 3507 | ad->u.net.sport = th->source; |
3508 | ad->u.net.dport = th->dest; | 3508 | ad->u.net.dport = th->dest; |
3509 | break; | 3509 | break; |
3510 | } | 3510 | } |
3511 | 3511 | ||
3512 | case IPPROTO_UDP: { | 3512 | case IPPROTO_UDP: { |
3513 | struct udphdr _udph, *uh; | 3513 | struct udphdr _udph, *uh; |
3514 | 3514 | ||
3515 | if (ntohs(ih->frag_off) & IP_OFFSET) | 3515 | if (ntohs(ih->frag_off) & IP_OFFSET) |
3516 | break; | 3516 | break; |
3517 | 3517 | ||
3518 | offset += ihlen; | 3518 | offset += ihlen; |
3519 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); | 3519 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); |
3520 | if (uh == NULL) | 3520 | if (uh == NULL) |
3521 | break; | 3521 | break; |
3522 | 3522 | ||
3523 | ad->u.net.sport = uh->source; | 3523 | ad->u.net.sport = uh->source; |
3524 | ad->u.net.dport = uh->dest; | 3524 | ad->u.net.dport = uh->dest; |
3525 | break; | 3525 | break; |
3526 | } | 3526 | } |
3527 | 3527 | ||
3528 | case IPPROTO_DCCP: { | 3528 | case IPPROTO_DCCP: { |
3529 | struct dccp_hdr _dccph, *dh; | 3529 | struct dccp_hdr _dccph, *dh; |
3530 | 3530 | ||
3531 | if (ntohs(ih->frag_off) & IP_OFFSET) | 3531 | if (ntohs(ih->frag_off) & IP_OFFSET) |
3532 | break; | 3532 | break; |
3533 | 3533 | ||
3534 | offset += ihlen; | 3534 | offset += ihlen; |
3535 | dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); | 3535 | dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); |
3536 | if (dh == NULL) | 3536 | if (dh == NULL) |
3537 | break; | 3537 | break; |
3538 | 3538 | ||
3539 | ad->u.net.sport = dh->dccph_sport; | 3539 | ad->u.net.sport = dh->dccph_sport; |
3540 | ad->u.net.dport = dh->dccph_dport; | 3540 | ad->u.net.dport = dh->dccph_dport; |
3541 | break; | 3541 | break; |
3542 | } | 3542 | } |
3543 | 3543 | ||
3544 | default: | 3544 | default: |
3545 | break; | 3545 | break; |
3546 | } | 3546 | } |
3547 | out: | 3547 | out: |
3548 | return ret; | 3548 | return ret; |
3549 | } | 3549 | } |
3550 | 3550 | ||
3551 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3551 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3552 | 3552 | ||
3553 | /* Returns error only if unable to parse addresses */ | 3553 | /* Returns error only if unable to parse addresses */ |
3554 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3554 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3555 | struct common_audit_data *ad, u8 *proto) | 3555 | struct common_audit_data *ad, u8 *proto) |
3556 | { | 3556 | { |
3557 | u8 nexthdr; | 3557 | u8 nexthdr; |
3558 | int ret = -EINVAL, offset; | 3558 | int ret = -EINVAL, offset; |
3559 | struct ipv6hdr _ipv6h, *ip6; | 3559 | struct ipv6hdr _ipv6h, *ip6; |
3560 | 3560 | ||
3561 | offset = skb_network_offset(skb); | 3561 | offset = skb_network_offset(skb); |
3562 | ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h); | 3562 | ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h); |
3563 | if (ip6 == NULL) | 3563 | if (ip6 == NULL) |
3564 | goto out; | 3564 | goto out; |
3565 | 3565 | ||
3566 | ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr); | 3566 | ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr); |
3567 | ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr); | 3567 | ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr); |
3568 | ret = 0; | 3568 | ret = 0; |
3569 | 3569 | ||
3570 | nexthdr = ip6->nexthdr; | 3570 | nexthdr = ip6->nexthdr; |
3571 | offset += sizeof(_ipv6h); | 3571 | offset += sizeof(_ipv6h); |
3572 | offset = ipv6_skip_exthdr(skb, offset, &nexthdr); | 3572 | offset = ipv6_skip_exthdr(skb, offset, &nexthdr); |
3573 | if (offset < 0) | 3573 | if (offset < 0) |
3574 | goto out; | 3574 | goto out; |
3575 | 3575 | ||
3576 | if (proto) | 3576 | if (proto) |
3577 | *proto = nexthdr; | 3577 | *proto = nexthdr; |
3578 | 3578 | ||
3579 | switch (nexthdr) { | 3579 | switch (nexthdr) { |
3580 | case IPPROTO_TCP: { | 3580 | case IPPROTO_TCP: { |
3581 | struct tcphdr _tcph, *th; | 3581 | struct tcphdr _tcph, *th; |
3582 | 3582 | ||
3583 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); | 3583 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); |
3584 | if (th == NULL) | 3584 | if (th == NULL) |
3585 | break; | 3585 | break; |
3586 | 3586 | ||
3587 | ad->u.net.sport = th->source; | 3587 | ad->u.net.sport = th->source; |
3588 | ad->u.net.dport = th->dest; | 3588 | ad->u.net.dport = th->dest; |
3589 | break; | 3589 | break; |
3590 | } | 3590 | } |
3591 | 3591 | ||
3592 | case IPPROTO_UDP: { | 3592 | case IPPROTO_UDP: { |
3593 | struct udphdr _udph, *uh; | 3593 | struct udphdr _udph, *uh; |
3594 | 3594 | ||
3595 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); | 3595 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); |
3596 | if (uh == NULL) | 3596 | if (uh == NULL) |
3597 | break; | 3597 | break; |
3598 | 3598 | ||
3599 | ad->u.net.sport = uh->source; | 3599 | ad->u.net.sport = uh->source; |
3600 | ad->u.net.dport = uh->dest; | 3600 | ad->u.net.dport = uh->dest; |
3601 | break; | 3601 | break; |
3602 | } | 3602 | } |
3603 | 3603 | ||
3604 | case IPPROTO_DCCP: { | 3604 | case IPPROTO_DCCP: { |
3605 | struct dccp_hdr _dccph, *dh; | 3605 | struct dccp_hdr _dccph, *dh; |
3606 | 3606 | ||
3607 | dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); | 3607 | dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); |
3608 | if (dh == NULL) | 3608 | if (dh == NULL) |
3609 | break; | 3609 | break; |
3610 | 3610 | ||
3611 | ad->u.net.sport = dh->dccph_sport; | 3611 | ad->u.net.sport = dh->dccph_sport; |
3612 | ad->u.net.dport = dh->dccph_dport; | 3612 | ad->u.net.dport = dh->dccph_dport; |
3613 | break; | 3613 | break; |
3614 | } | 3614 | } |
3615 | 3615 | ||
3616 | /* includes fragments */ | 3616 | /* includes fragments */ |
3617 | default: | 3617 | default: |
3618 | break; | 3618 | break; |
3619 | } | 3619 | } |
3620 | out: | 3620 | out: |
3621 | return ret; | 3621 | return ret; |
3622 | } | 3622 | } |
3623 | 3623 | ||
3624 | #endif /* IPV6 */ | 3624 | #endif /* IPV6 */ |
3625 | 3625 | ||
3626 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, | 3626 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3627 | char **_addrp, int src, u8 *proto) | 3627 | char **_addrp, int src, u8 *proto) |
3628 | { | 3628 | { |
3629 | char *addrp; | 3629 | char *addrp; |
3630 | int ret; | 3630 | int ret; |
3631 | 3631 | ||
3632 | switch (ad->u.net.family) { | 3632 | switch (ad->u.net.family) { |
3633 | case PF_INET: | 3633 | case PF_INET: |
3634 | ret = selinux_parse_skb_ipv4(skb, ad, proto); | 3634 | ret = selinux_parse_skb_ipv4(skb, ad, proto); |
3635 | if (ret) | 3635 | if (ret) |
3636 | goto parse_error; | 3636 | goto parse_error; |
3637 | addrp = (char *)(src ? &ad->u.net.v4info.saddr : | 3637 | addrp = (char *)(src ? &ad->u.net.v4info.saddr : |
3638 | &ad->u.net.v4info.daddr); | 3638 | &ad->u.net.v4info.daddr); |
3639 | goto okay; | 3639 | goto okay; |
3640 | 3640 | ||
3641 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3641 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3642 | case PF_INET6: | 3642 | case PF_INET6: |
3643 | ret = selinux_parse_skb_ipv6(skb, ad, proto); | 3643 | ret = selinux_parse_skb_ipv6(skb, ad, proto); |
3644 | if (ret) | 3644 | if (ret) |
3645 | goto parse_error; | 3645 | goto parse_error; |
3646 | addrp = (char *)(src ? &ad->u.net.v6info.saddr : | 3646 | addrp = (char *)(src ? &ad->u.net.v6info.saddr : |
3647 | &ad->u.net.v6info.daddr); | 3647 | &ad->u.net.v6info.daddr); |
3648 | goto okay; | 3648 | goto okay; |
3649 | #endif /* IPV6 */ | 3649 | #endif /* IPV6 */ |
3650 | default: | 3650 | default: |
3651 | addrp = NULL; | 3651 | addrp = NULL; |
3652 | goto okay; | 3652 | goto okay; |
3653 | } | 3653 | } |
3654 | 3654 | ||
3655 | parse_error: | 3655 | parse_error: |
3656 | printk(KERN_WARNING | 3656 | printk(KERN_WARNING |
3657 | "SELinux: failure in selinux_parse_skb()," | 3657 | "SELinux: failure in selinux_parse_skb()," |
3658 | " unable to parse packet\n"); | 3658 | " unable to parse packet\n"); |
3659 | return ret; | 3659 | return ret; |
3660 | 3660 | ||
3661 | okay: | 3661 | okay: |
3662 | if (_addrp) | 3662 | if (_addrp) |
3663 | *_addrp = addrp; | 3663 | *_addrp = addrp; |
3664 | return 0; | 3664 | return 0; |
3665 | } | 3665 | } |
3666 | 3666 | ||
3667 | /** | 3667 | /** |
3668 | * selinux_skb_peerlbl_sid - Determine the peer label of a packet | 3668 | * selinux_skb_peerlbl_sid - Determine the peer label of a packet |
3669 | * @skb: the packet | 3669 | * @skb: the packet |
3670 | * @family: protocol family | 3670 | * @family: protocol family |
3671 | * @sid: the packet's peer label SID | 3671 | * @sid: the packet's peer label SID |
3672 | * | 3672 | * |
3673 | * Description: | 3673 | * Description: |
3674 | * Check the various different forms of network peer labeling and determine | 3674 | * Check the various different forms of network peer labeling and determine |
3675 | * the peer label/SID for the packet; most of the magic actually occurs in | 3675 | * the peer label/SID for the packet; most of the magic actually occurs in |
3676 | * the security server function security_net_peersid_cmp(). The function | 3676 | * the security server function security_net_peersid_cmp(). The function |
3677 | * returns zero if the value in @sid is valid (although it may be SECSID_NULL) | 3677 | * returns zero if the value in @sid is valid (although it may be SECSID_NULL) |
3678 | * or -EACCES if @sid is invalid due to inconsistencies with the different | 3678 | * or -EACCES if @sid is invalid due to inconsistencies with the different |
3679 | * peer labels. | 3679 | * peer labels. |
3680 | * | 3680 | * |
3681 | */ | 3681 | */ |
3682 | static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | 3682 | static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) |
3683 | { | 3683 | { |
3684 | int err; | 3684 | int err; |
3685 | u32 xfrm_sid; | 3685 | u32 xfrm_sid; |
3686 | u32 nlbl_sid; | 3686 | u32 nlbl_sid; |
3687 | u32 nlbl_type; | 3687 | u32 nlbl_type; |
3688 | 3688 | ||
3689 | selinux_skb_xfrm_sid(skb, &xfrm_sid); | 3689 | selinux_skb_xfrm_sid(skb, &xfrm_sid); |
3690 | selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); | 3690 | selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); |
3691 | 3691 | ||
3692 | err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); | 3692 | err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); |
3693 | if (unlikely(err)) { | 3693 | if (unlikely(err)) { |
3694 | printk(KERN_WARNING | 3694 | printk(KERN_WARNING |
3695 | "SELinux: failure in selinux_skb_peerlbl_sid()," | 3695 | "SELinux: failure in selinux_skb_peerlbl_sid()," |
3696 | " unable to determine packet's peer label\n"); | 3696 | " unable to determine packet's peer label\n"); |
3697 | return -EACCES; | 3697 | return -EACCES; |
3698 | } | 3698 | } |
3699 | 3699 | ||
3700 | return 0; | 3700 | return 0; |
3701 | } | 3701 | } |
3702 | 3702 | ||
3703 | /* socket security operations */ | 3703 | /* socket security operations */ |
3704 | 3704 | ||
3705 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, | 3705 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, |
3706 | u16 secclass, u32 *socksid) | 3706 | u16 secclass, u32 *socksid) |
3707 | { | 3707 | { |
3708 | if (tsec->sockcreate_sid > SECSID_NULL) { | 3708 | if (tsec->sockcreate_sid > SECSID_NULL) { |
3709 | *socksid = tsec->sockcreate_sid; | 3709 | *socksid = tsec->sockcreate_sid; |
3710 | return 0; | 3710 | return 0; |
3711 | } | 3711 | } |
3712 | 3712 | ||
3713 | return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, | 3713 | return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, |
3714 | socksid); | 3714 | socksid); |
3715 | } | 3715 | } |
3716 | 3716 | ||
3717 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | 3717 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3718 | { | 3718 | { |
3719 | struct sk_security_struct *sksec = sk->sk_security; | 3719 | struct sk_security_struct *sksec = sk->sk_security; |
3720 | struct common_audit_data ad; | 3720 | struct common_audit_data ad; |
3721 | u32 tsid = task_sid(task); | 3721 | u32 tsid = task_sid(task); |
3722 | 3722 | ||
3723 | if (sksec->sid == SECINITSID_KERNEL) | 3723 | if (sksec->sid == SECINITSID_KERNEL) |
3724 | return 0; | 3724 | return 0; |
3725 | 3725 | ||
3726 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3726 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3727 | ad.u.net.sk = sk; | 3727 | ad.u.net.sk = sk; |
3728 | 3728 | ||
3729 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); | 3729 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3730 | } | 3730 | } |
3731 | 3731 | ||
3732 | static int selinux_socket_create(int family, int type, | 3732 | static int selinux_socket_create(int family, int type, |
3733 | int protocol, int kern) | 3733 | int protocol, int kern) |
3734 | { | 3734 | { |
3735 | const struct task_security_struct *tsec = current_security(); | 3735 | const struct task_security_struct *tsec = current_security(); |
3736 | u32 newsid; | 3736 | u32 newsid; |
3737 | u16 secclass; | 3737 | u16 secclass; |
3738 | int rc; | 3738 | int rc; |
3739 | 3739 | ||
3740 | if (kern) | 3740 | if (kern) |
3741 | return 0; | 3741 | return 0; |
3742 | 3742 | ||
3743 | secclass = socket_type_to_security_class(family, type, protocol); | 3743 | secclass = socket_type_to_security_class(family, type, protocol); |
3744 | rc = socket_sockcreate_sid(tsec, secclass, &newsid); | 3744 | rc = socket_sockcreate_sid(tsec, secclass, &newsid); |
3745 | if (rc) | 3745 | if (rc) |
3746 | return rc; | 3746 | return rc; |
3747 | 3747 | ||
3748 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); | 3748 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3749 | } | 3749 | } |
3750 | 3750 | ||
3751 | static int selinux_socket_post_create(struct socket *sock, int family, | 3751 | static int selinux_socket_post_create(struct socket *sock, int family, |
3752 | int type, int protocol, int kern) | 3752 | int type, int protocol, int kern) |
3753 | { | 3753 | { |
3754 | const struct task_security_struct *tsec = current_security(); | 3754 | const struct task_security_struct *tsec = current_security(); |
3755 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | 3755 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3756 | struct sk_security_struct *sksec; | 3756 | struct sk_security_struct *sksec; |
3757 | int err = 0; | 3757 | int err = 0; |
3758 | 3758 | ||
3759 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3759 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3760 | 3760 | ||
3761 | if (kern) | 3761 | if (kern) |
3762 | isec->sid = SECINITSID_KERNEL; | 3762 | isec->sid = SECINITSID_KERNEL; |
3763 | else { | 3763 | else { |
3764 | err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid)); | 3764 | err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid)); |
3765 | if (err) | 3765 | if (err) |
3766 | return err; | 3766 | return err; |
3767 | } | 3767 | } |
3768 | 3768 | ||
3769 | isec->initialized = 1; | 3769 | isec->initialized = 1; |
3770 | 3770 | ||
3771 | if (sock->sk) { | 3771 | if (sock->sk) { |
3772 | sksec = sock->sk->sk_security; | 3772 | sksec = sock->sk->sk_security; |
3773 | sksec->sid = isec->sid; | 3773 | sksec->sid = isec->sid; |
3774 | sksec->sclass = isec->sclass; | 3774 | sksec->sclass = isec->sclass; |
3775 | err = selinux_netlbl_socket_post_create(sock->sk, family); | 3775 | err = selinux_netlbl_socket_post_create(sock->sk, family); |
3776 | } | 3776 | } |
3777 | 3777 | ||
3778 | return err; | 3778 | return err; |
3779 | } | 3779 | } |
3780 | 3780 | ||
3781 | /* Range of port numbers used to automatically bind. | 3781 | /* Range of port numbers used to automatically bind. |
3782 | Need to determine whether we should perform a name_bind | 3782 | Need to determine whether we should perform a name_bind |
3783 | permission check between the socket and the port number. */ | 3783 | permission check between the socket and the port number. */ |
3784 | 3784 | ||
3785 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3785 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3786 | { | 3786 | { |
3787 | struct sock *sk = sock->sk; | 3787 | struct sock *sk = sock->sk; |
3788 | u16 family; | 3788 | u16 family; |
3789 | int err; | 3789 | int err; |
3790 | 3790 | ||
3791 | err = sock_has_perm(current, sk, SOCKET__BIND); | 3791 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3792 | if (err) | 3792 | if (err) |
3793 | goto out; | 3793 | goto out; |
3794 | 3794 | ||
3795 | /* | 3795 | /* |
3796 | * If PF_INET or PF_INET6, check name_bind permission for the port. | 3796 | * If PF_INET or PF_INET6, check name_bind permission for the port. |
3797 | * Multiple address binding for SCTP is not supported yet: we just | 3797 | * Multiple address binding for SCTP is not supported yet: we just |
3798 | * check the first address now. | 3798 | * check the first address now. |
3799 | */ | 3799 | */ |
3800 | family = sk->sk_family; | 3800 | family = sk->sk_family; |
3801 | if (family == PF_INET || family == PF_INET6) { | 3801 | if (family == PF_INET || family == PF_INET6) { |
3802 | char *addrp; | 3802 | char *addrp; |
3803 | struct sk_security_struct *sksec = sk->sk_security; | 3803 | struct sk_security_struct *sksec = sk->sk_security; |
3804 | struct common_audit_data ad; | 3804 | struct common_audit_data ad; |
3805 | struct sockaddr_in *addr4 = NULL; | 3805 | struct sockaddr_in *addr4 = NULL; |
3806 | struct sockaddr_in6 *addr6 = NULL; | 3806 | struct sockaddr_in6 *addr6 = NULL; |
3807 | unsigned short snum; | 3807 | unsigned short snum; |
3808 | u32 sid, node_perm; | 3808 | u32 sid, node_perm; |
3809 | 3809 | ||
3810 | if (family == PF_INET) { | 3810 | if (family == PF_INET) { |
3811 | addr4 = (struct sockaddr_in *)address; | 3811 | addr4 = (struct sockaddr_in *)address; |
3812 | snum = ntohs(addr4->sin_port); | 3812 | snum = ntohs(addr4->sin_port); |
3813 | addrp = (char *)&addr4->sin_addr.s_addr; | 3813 | addrp = (char *)&addr4->sin_addr.s_addr; |
3814 | } else { | 3814 | } else { |
3815 | addr6 = (struct sockaddr_in6 *)address; | 3815 | addr6 = (struct sockaddr_in6 *)address; |
3816 | snum = ntohs(addr6->sin6_port); | 3816 | snum = ntohs(addr6->sin6_port); |
3817 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 3817 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
3818 | } | 3818 | } |
3819 | 3819 | ||
3820 | if (snum) { | 3820 | if (snum) { |
3821 | int low, high; | 3821 | int low, high; |
3822 | 3822 | ||
3823 | inet_get_local_port_range(&low, &high); | 3823 | inet_get_local_port_range(&low, &high); |
3824 | 3824 | ||
3825 | if (snum < max(PROT_SOCK, low) || snum > high) { | 3825 | if (snum < max(PROT_SOCK, low) || snum > high) { |
3826 | err = sel_netport_sid(sk->sk_protocol, | 3826 | err = sel_netport_sid(sk->sk_protocol, |
3827 | snum, &sid); | 3827 | snum, &sid); |
3828 | if (err) | 3828 | if (err) |
3829 | goto out; | 3829 | goto out; |
3830 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3830 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3831 | ad.u.net.sport = htons(snum); | 3831 | ad.u.net.sport = htons(snum); |
3832 | ad.u.net.family = family; | 3832 | ad.u.net.family = family; |
3833 | err = avc_has_perm(sksec->sid, sid, | 3833 | err = avc_has_perm(sksec->sid, sid, |
3834 | sksec->sclass, | 3834 | sksec->sclass, |
3835 | SOCKET__NAME_BIND, &ad); | 3835 | SOCKET__NAME_BIND, &ad); |
3836 | if (err) | 3836 | if (err) |
3837 | goto out; | 3837 | goto out; |
3838 | } | 3838 | } |
3839 | } | 3839 | } |
3840 | 3840 | ||
3841 | switch (sksec->sclass) { | 3841 | switch (sksec->sclass) { |
3842 | case SECCLASS_TCP_SOCKET: | 3842 | case SECCLASS_TCP_SOCKET: |
3843 | node_perm = TCP_SOCKET__NODE_BIND; | 3843 | node_perm = TCP_SOCKET__NODE_BIND; |
3844 | break; | 3844 | break; |
3845 | 3845 | ||
3846 | case SECCLASS_UDP_SOCKET: | 3846 | case SECCLASS_UDP_SOCKET: |
3847 | node_perm = UDP_SOCKET__NODE_BIND; | 3847 | node_perm = UDP_SOCKET__NODE_BIND; |
3848 | break; | 3848 | break; |
3849 | 3849 | ||
3850 | case SECCLASS_DCCP_SOCKET: | 3850 | case SECCLASS_DCCP_SOCKET: |
3851 | node_perm = DCCP_SOCKET__NODE_BIND; | 3851 | node_perm = DCCP_SOCKET__NODE_BIND; |
3852 | break; | 3852 | break; |
3853 | 3853 | ||
3854 | default: | 3854 | default: |
3855 | node_perm = RAWIP_SOCKET__NODE_BIND; | 3855 | node_perm = RAWIP_SOCKET__NODE_BIND; |
3856 | break; | 3856 | break; |
3857 | } | 3857 | } |
3858 | 3858 | ||
3859 | err = sel_netnode_sid(addrp, family, &sid); | 3859 | err = sel_netnode_sid(addrp, family, &sid); |
3860 | if (err) | 3860 | if (err) |
3861 | goto out; | 3861 | goto out; |
3862 | 3862 | ||
3863 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3863 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3864 | ad.u.net.sport = htons(snum); | 3864 | ad.u.net.sport = htons(snum); |
3865 | ad.u.net.family = family; | 3865 | ad.u.net.family = family; |
3866 | 3866 | ||
3867 | if (family == PF_INET) | 3867 | if (family == PF_INET) |
3868 | ad.u.net.v4info.saddr = addr4->sin_addr.s_addr; | 3868 | ad.u.net.v4info.saddr = addr4->sin_addr.s_addr; |
3869 | else | 3869 | else |
3870 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3870 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3871 | 3871 | ||
3872 | err = avc_has_perm(sksec->sid, sid, | 3872 | err = avc_has_perm(sksec->sid, sid, |
3873 | sksec->sclass, node_perm, &ad); | 3873 | sksec->sclass, node_perm, &ad); |
3874 | if (err) | 3874 | if (err) |
3875 | goto out; | 3875 | goto out; |
3876 | } | 3876 | } |
3877 | out: | 3877 | out: |
3878 | return err; | 3878 | return err; |
3879 | } | 3879 | } |
3880 | 3880 | ||
3881 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3881 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3882 | { | 3882 | { |
3883 | struct sock *sk = sock->sk; | 3883 | struct sock *sk = sock->sk; |
3884 | struct sk_security_struct *sksec = sk->sk_security; | 3884 | struct sk_security_struct *sksec = sk->sk_security; |
3885 | int err; | 3885 | int err; |
3886 | 3886 | ||
3887 | err = sock_has_perm(current, sk, SOCKET__CONNECT); | 3887 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3888 | if (err) | 3888 | if (err) |
3889 | return err; | 3889 | return err; |
3890 | 3890 | ||
3891 | /* | 3891 | /* |
3892 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3892 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3893 | */ | 3893 | */ |
3894 | if (sksec->sclass == SECCLASS_TCP_SOCKET || | 3894 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3895 | sksec->sclass == SECCLASS_DCCP_SOCKET) { | 3895 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3896 | struct common_audit_data ad; | 3896 | struct common_audit_data ad; |
3897 | struct sockaddr_in *addr4 = NULL; | 3897 | struct sockaddr_in *addr4 = NULL; |
3898 | struct sockaddr_in6 *addr6 = NULL; | 3898 | struct sockaddr_in6 *addr6 = NULL; |
3899 | unsigned short snum; | 3899 | unsigned short snum; |
3900 | u32 sid, perm; | 3900 | u32 sid, perm; |
3901 | 3901 | ||
3902 | if (sk->sk_family == PF_INET) { | 3902 | if (sk->sk_family == PF_INET) { |
3903 | addr4 = (struct sockaddr_in *)address; | 3903 | addr4 = (struct sockaddr_in *)address; |
3904 | if (addrlen < sizeof(struct sockaddr_in)) | 3904 | if (addrlen < sizeof(struct sockaddr_in)) |
3905 | return -EINVAL; | 3905 | return -EINVAL; |
3906 | snum = ntohs(addr4->sin_port); | 3906 | snum = ntohs(addr4->sin_port); |
3907 | } else { | 3907 | } else { |
3908 | addr6 = (struct sockaddr_in6 *)address; | 3908 | addr6 = (struct sockaddr_in6 *)address; |
3909 | if (addrlen < SIN6_LEN_RFC2133) | 3909 | if (addrlen < SIN6_LEN_RFC2133) |
3910 | return -EINVAL; | 3910 | return -EINVAL; |
3911 | snum = ntohs(addr6->sin6_port); | 3911 | snum = ntohs(addr6->sin6_port); |
3912 | } | 3912 | } |
3913 | 3913 | ||
3914 | err = sel_netport_sid(sk->sk_protocol, snum, &sid); | 3914 | err = sel_netport_sid(sk->sk_protocol, snum, &sid); |
3915 | if (err) | 3915 | if (err) |
3916 | goto out; | 3916 | goto out; |
3917 | 3917 | ||
3918 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? | 3918 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3919 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3919 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3920 | 3920 | ||
3921 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3921 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3922 | ad.u.net.dport = htons(snum); | 3922 | ad.u.net.dport = htons(snum); |
3923 | ad.u.net.family = sk->sk_family; | 3923 | ad.u.net.family = sk->sk_family; |
3924 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); | 3924 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3925 | if (err) | 3925 | if (err) |
3926 | goto out; | 3926 | goto out; |
3927 | } | 3927 | } |
3928 | 3928 | ||
3929 | err = selinux_netlbl_socket_connect(sk, address); | 3929 | err = selinux_netlbl_socket_connect(sk, address); |
3930 | 3930 | ||
3931 | out: | 3931 | out: |
3932 | return err; | 3932 | return err; |
3933 | } | 3933 | } |
3934 | 3934 | ||
3935 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3935 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3936 | { | 3936 | { |
3937 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); | 3937 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3938 | } | 3938 | } |
3939 | 3939 | ||
3940 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3940 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
3941 | { | 3941 | { |
3942 | int err; | 3942 | int err; |
3943 | struct inode_security_struct *isec; | 3943 | struct inode_security_struct *isec; |
3944 | struct inode_security_struct *newisec; | 3944 | struct inode_security_struct *newisec; |
3945 | 3945 | ||
3946 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); | 3946 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3947 | if (err) | 3947 | if (err) |
3948 | return err; | 3948 | return err; |
3949 | 3949 | ||
3950 | newisec = SOCK_INODE(newsock)->i_security; | 3950 | newisec = SOCK_INODE(newsock)->i_security; |
3951 | 3951 | ||
3952 | isec = SOCK_INODE(sock)->i_security; | 3952 | isec = SOCK_INODE(sock)->i_security; |
3953 | newisec->sclass = isec->sclass; | 3953 | newisec->sclass = isec->sclass; |
3954 | newisec->sid = isec->sid; | 3954 | newisec->sid = isec->sid; |
3955 | newisec->initialized = 1; | 3955 | newisec->initialized = 1; |
3956 | 3956 | ||
3957 | return 0; | 3957 | return 0; |
3958 | } | 3958 | } |
3959 | 3959 | ||
3960 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3960 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3961 | int size) | 3961 | int size) |
3962 | { | 3962 | { |
3963 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); | 3963 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3964 | } | 3964 | } |
3965 | 3965 | ||
3966 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3966 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3967 | int size, int flags) | 3967 | int size, int flags) |
3968 | { | 3968 | { |
3969 | return sock_has_perm(current, sock->sk, SOCKET__READ); | 3969 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3970 | } | 3970 | } |
3971 | 3971 | ||
3972 | static int selinux_socket_getsockname(struct socket *sock) | 3972 | static int selinux_socket_getsockname(struct socket *sock) |
3973 | { | 3973 | { |
3974 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 3974 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3975 | } | 3975 | } |
3976 | 3976 | ||
3977 | static int selinux_socket_getpeername(struct socket *sock) | 3977 | static int selinux_socket_getpeername(struct socket *sock) |
3978 | { | 3978 | { |
3979 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 3979 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3980 | } | 3980 | } |
3981 | 3981 | ||
3982 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3982 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3983 | { | 3983 | { |
3984 | int err; | 3984 | int err; |
3985 | 3985 | ||
3986 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); | 3986 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3987 | if (err) | 3987 | if (err) |
3988 | return err; | 3988 | return err; |
3989 | 3989 | ||
3990 | return selinux_netlbl_socket_setsockopt(sock, level, optname); | 3990 | return selinux_netlbl_socket_setsockopt(sock, level, optname); |
3991 | } | 3991 | } |
3992 | 3992 | ||
3993 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3993 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3994 | int optname) | 3994 | int optname) |
3995 | { | 3995 | { |
3996 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); | 3996 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3997 | } | 3997 | } |
3998 | 3998 | ||
3999 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3999 | static int selinux_socket_shutdown(struct socket *sock, int how) |
4000 | { | 4000 | { |
4001 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); | 4001 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
4002 | } | 4002 | } |
4003 | 4003 | ||
4004 | static int selinux_socket_unix_stream_connect(struct sock *sock, | 4004 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
4005 | struct sock *other, | 4005 | struct sock *other, |
4006 | struct sock *newsk) | 4006 | struct sock *newsk) |
4007 | { | 4007 | { |
4008 | struct sk_security_struct *sksec_sock = sock->sk_security; | 4008 | struct sk_security_struct *sksec_sock = sock->sk_security; |
4009 | struct sk_security_struct *sksec_other = other->sk_security; | 4009 | struct sk_security_struct *sksec_other = other->sk_security; |
4010 | struct sk_security_struct *sksec_new = newsk->sk_security; | 4010 | struct sk_security_struct *sksec_new = newsk->sk_security; |
4011 | struct common_audit_data ad; | 4011 | struct common_audit_data ad; |
4012 | int err; | 4012 | int err; |
4013 | 4013 | ||
4014 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4014 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4015 | ad.u.net.sk = other; | 4015 | ad.u.net.sk = other; |
4016 | 4016 | ||
4017 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, | 4017 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
4018 | sksec_other->sclass, | 4018 | sksec_other->sclass, |
4019 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 4019 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
4020 | if (err) | 4020 | if (err) |
4021 | return err; | 4021 | return err; |
4022 | 4022 | ||
4023 | /* server child socket */ | 4023 | /* server child socket */ |
4024 | sksec_new->peer_sid = sksec_sock->sid; | 4024 | sksec_new->peer_sid = sksec_sock->sid; |
4025 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, | 4025 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
4026 | &sksec_new->sid); | 4026 | &sksec_new->sid); |
4027 | if (err) | 4027 | if (err) |
4028 | return err; | 4028 | return err; |
4029 | 4029 | ||
4030 | /* connecting socket */ | 4030 | /* connecting socket */ |
4031 | sksec_sock->peer_sid = sksec_new->sid; | 4031 | sksec_sock->peer_sid = sksec_new->sid; |
4032 | 4032 | ||
4033 | return 0; | 4033 | return 0; |
4034 | } | 4034 | } |
4035 | 4035 | ||
4036 | static int selinux_socket_unix_may_send(struct socket *sock, | 4036 | static int selinux_socket_unix_may_send(struct socket *sock, |
4037 | struct socket *other) | 4037 | struct socket *other) |
4038 | { | 4038 | { |
4039 | struct sk_security_struct *ssec = sock->sk->sk_security; | 4039 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4040 | struct sk_security_struct *osec = other->sk->sk_security; | 4040 | struct sk_security_struct *osec = other->sk->sk_security; |
4041 | struct common_audit_data ad; | 4041 | struct common_audit_data ad; |
4042 | 4042 | ||
4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4044 | ad.u.net.sk = other->sk; | 4044 | ad.u.net.sk = other->sk; |
4045 | 4045 | ||
4046 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, | 4046 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
4047 | &ad); | 4047 | &ad); |
4048 | } | 4048 | } |
4049 | 4049 | ||
4050 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4050 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
4051 | u32 peer_sid, | 4051 | u32 peer_sid, |
4052 | struct common_audit_data *ad) | 4052 | struct common_audit_data *ad) |
4053 | { | 4053 | { |
4054 | int err; | 4054 | int err; |
4055 | u32 if_sid; | 4055 | u32 if_sid; |
4056 | u32 node_sid; | 4056 | u32 node_sid; |
4057 | 4057 | ||
4058 | err = sel_netif_sid(ifindex, &if_sid); | 4058 | err = sel_netif_sid(ifindex, &if_sid); |
4059 | if (err) | 4059 | if (err) |
4060 | return err; | 4060 | return err; |
4061 | err = avc_has_perm(peer_sid, if_sid, | 4061 | err = avc_has_perm(peer_sid, if_sid, |
4062 | SECCLASS_NETIF, NETIF__INGRESS, ad); | 4062 | SECCLASS_NETIF, NETIF__INGRESS, ad); |
4063 | if (err) | 4063 | if (err) |
4064 | return err; | 4064 | return err; |
4065 | 4065 | ||
4066 | err = sel_netnode_sid(addrp, family, &node_sid); | 4066 | err = sel_netnode_sid(addrp, family, &node_sid); |
4067 | if (err) | 4067 | if (err) |
4068 | return err; | 4068 | return err; |
4069 | return avc_has_perm(peer_sid, node_sid, | 4069 | return avc_has_perm(peer_sid, node_sid, |
4070 | SECCLASS_NODE, NODE__RECVFROM, ad); | 4070 | SECCLASS_NODE, NODE__RECVFROM, ad); |
4071 | } | 4071 | } |
4072 | 4072 | ||
4073 | static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | 4073 | static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, |
4074 | u16 family) | 4074 | u16 family) |
4075 | { | 4075 | { |
4076 | int err = 0; | 4076 | int err = 0; |
4077 | struct sk_security_struct *sksec = sk->sk_security; | 4077 | struct sk_security_struct *sksec = sk->sk_security; |
4078 | u32 sk_sid = sksec->sid; | 4078 | u32 sk_sid = sksec->sid; |
4079 | struct common_audit_data ad; | 4079 | struct common_audit_data ad; |
4080 | char *addrp; | 4080 | char *addrp; |
4081 | 4081 | ||
4082 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4082 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4083 | ad.u.net.netif = skb->skb_iif; | 4083 | ad.u.net.netif = skb->skb_iif; |
4084 | ad.u.net.family = family; | 4084 | ad.u.net.family = family; |
4085 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4085 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4086 | if (err) | 4086 | if (err) |
4087 | return err; | 4087 | return err; |
4088 | 4088 | ||
4089 | if (selinux_secmark_enabled()) { | 4089 | if (selinux_secmark_enabled()) { |
4090 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 4090 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, |
4091 | PACKET__RECV, &ad); | 4091 | PACKET__RECV, &ad); |
4092 | if (err) | 4092 | if (err) |
4093 | return err; | 4093 | return err; |
4094 | } | 4094 | } |
4095 | 4095 | ||
4096 | err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); | 4096 | err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); |
4097 | if (err) | 4097 | if (err) |
4098 | return err; | 4098 | return err; |
4099 | err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); | 4099 | err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); |
4100 | 4100 | ||
4101 | return err; | 4101 | return err; |
4102 | } | 4102 | } |
4103 | 4103 | ||
4104 | static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 4104 | static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
4105 | { | 4105 | { |
4106 | int err; | 4106 | int err; |
4107 | struct sk_security_struct *sksec = sk->sk_security; | 4107 | struct sk_security_struct *sksec = sk->sk_security; |
4108 | u16 family = sk->sk_family; | 4108 | u16 family = sk->sk_family; |
4109 | u32 sk_sid = sksec->sid; | 4109 | u32 sk_sid = sksec->sid; |
4110 | struct common_audit_data ad; | 4110 | struct common_audit_data ad; |
4111 | char *addrp; | 4111 | char *addrp; |
4112 | u8 secmark_active; | 4112 | u8 secmark_active; |
4113 | u8 peerlbl_active; | 4113 | u8 peerlbl_active; |
4114 | 4114 | ||
4115 | if (family != PF_INET && family != PF_INET6) | 4115 | if (family != PF_INET && family != PF_INET6) |
4116 | return 0; | 4116 | return 0; |
4117 | 4117 | ||
4118 | /* Handle mapped IPv4 packets arriving via IPv6 sockets */ | 4118 | /* Handle mapped IPv4 packets arriving via IPv6 sockets */ |
4119 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 4119 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
4120 | family = PF_INET; | 4120 | family = PF_INET; |
4121 | 4121 | ||
4122 | /* If any sort of compatibility mode is enabled then handoff processing | 4122 | /* If any sort of compatibility mode is enabled then handoff processing |
4123 | * to the selinux_sock_rcv_skb_compat() function to deal with the | 4123 | * to the selinux_sock_rcv_skb_compat() function to deal with the |
4124 | * special handling. We do this in an attempt to keep this function | 4124 | * special handling. We do this in an attempt to keep this function |
4125 | * as fast and as clean as possible. */ | 4125 | * as fast and as clean as possible. */ |
4126 | if (!selinux_policycap_netpeer) | 4126 | if (!selinux_policycap_netpeer) |
4127 | return selinux_sock_rcv_skb_compat(sk, skb, family); | 4127 | return selinux_sock_rcv_skb_compat(sk, skb, family); |
4128 | 4128 | ||
4129 | secmark_active = selinux_secmark_enabled(); | 4129 | secmark_active = selinux_secmark_enabled(); |
4130 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); | 4130 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); |
4131 | if (!secmark_active && !peerlbl_active) | 4131 | if (!secmark_active && !peerlbl_active) |
4132 | return 0; | 4132 | return 0; |
4133 | 4133 | ||
4134 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4134 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4135 | ad.u.net.netif = skb->skb_iif; | 4135 | ad.u.net.netif = skb->skb_iif; |
4136 | ad.u.net.family = family; | 4136 | ad.u.net.family = family; |
4137 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4137 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4138 | if (err) | 4138 | if (err) |
4139 | return err; | 4139 | return err; |
4140 | 4140 | ||
4141 | if (peerlbl_active) { | 4141 | if (peerlbl_active) { |
4142 | u32 peer_sid; | 4142 | u32 peer_sid; |
4143 | 4143 | ||
4144 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4144 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
4145 | if (err) | 4145 | if (err) |
4146 | return err; | 4146 | return err; |
4147 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, | 4147 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, |
4148 | peer_sid, &ad); | 4148 | peer_sid, &ad); |
4149 | if (err) { | 4149 | if (err) { |
4150 | selinux_netlbl_err(skb, err, 0); | 4150 | selinux_netlbl_err(skb, err, 0); |
4151 | return err; | 4151 | return err; |
4152 | } | 4152 | } |
4153 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, | 4153 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, |
4154 | PEER__RECV, &ad); | 4154 | PEER__RECV, &ad); |
4155 | if (err) | 4155 | if (err) |
4156 | selinux_netlbl_err(skb, err, 0); | 4156 | selinux_netlbl_err(skb, err, 0); |
4157 | } | 4157 | } |
4158 | 4158 | ||
4159 | if (secmark_active) { | 4159 | if (secmark_active) { |
4160 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 4160 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, |
4161 | PACKET__RECV, &ad); | 4161 | PACKET__RECV, &ad); |
4162 | if (err) | 4162 | if (err) |
4163 | return err; | 4163 | return err; |
4164 | } | 4164 | } |
4165 | 4165 | ||
4166 | return err; | 4166 | return err; |
4167 | } | 4167 | } |
4168 | 4168 | ||
4169 | static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, | 4169 | static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
4170 | int __user *optlen, unsigned len) | 4170 | int __user *optlen, unsigned len) |
4171 | { | 4171 | { |
4172 | int err = 0; | 4172 | int err = 0; |
4173 | char *scontext; | 4173 | char *scontext; |
4174 | u32 scontext_len; | 4174 | u32 scontext_len; |
4175 | struct sk_security_struct *sksec = sock->sk->sk_security; | 4175 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4176 | u32 peer_sid = SECSID_NULL; | 4176 | u32 peer_sid = SECSID_NULL; |
4177 | 4177 | ||
4178 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4178 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4179 | sksec->sclass == SECCLASS_TCP_SOCKET) | 4179 | sksec->sclass == SECCLASS_TCP_SOCKET) |
4180 | peer_sid = sksec->peer_sid; | 4180 | peer_sid = sksec->peer_sid; |
4181 | if (peer_sid == SECSID_NULL) | 4181 | if (peer_sid == SECSID_NULL) |
4182 | return -ENOPROTOOPT; | 4182 | return -ENOPROTOOPT; |
4183 | 4183 | ||
4184 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4184 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4185 | if (err) | 4185 | if (err) |
4186 | return err; | 4186 | return err; |
4187 | 4187 | ||
4188 | if (scontext_len > len) { | 4188 | if (scontext_len > len) { |
4189 | err = -ERANGE; | 4189 | err = -ERANGE; |
4190 | goto out_len; | 4190 | goto out_len; |
4191 | } | 4191 | } |
4192 | 4192 | ||
4193 | if (copy_to_user(optval, scontext, scontext_len)) | 4193 | if (copy_to_user(optval, scontext, scontext_len)) |
4194 | err = -EFAULT; | 4194 | err = -EFAULT; |
4195 | 4195 | ||
4196 | out_len: | 4196 | out_len: |
4197 | if (put_user(scontext_len, optlen)) | 4197 | if (put_user(scontext_len, optlen)) |
4198 | err = -EFAULT; | 4198 | err = -EFAULT; |
4199 | kfree(scontext); | 4199 | kfree(scontext); |
4200 | return err; | 4200 | return err; |
4201 | } | 4201 | } |
4202 | 4202 | ||
4203 | static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) | 4203 | static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) |
4204 | { | 4204 | { |
4205 | u32 peer_secid = SECSID_NULL; | 4205 | u32 peer_secid = SECSID_NULL; |
4206 | u16 family; | 4206 | u16 family; |
4207 | 4207 | ||
4208 | if (skb && skb->protocol == htons(ETH_P_IP)) | 4208 | if (skb && skb->protocol == htons(ETH_P_IP)) |
4209 | family = PF_INET; | 4209 | family = PF_INET; |
4210 | else if (skb && skb->protocol == htons(ETH_P_IPV6)) | 4210 | else if (skb && skb->protocol == htons(ETH_P_IPV6)) |
4211 | family = PF_INET6; | 4211 | family = PF_INET6; |
4212 | else if (sock) | 4212 | else if (sock) |
4213 | family = sock->sk->sk_family; | 4213 | family = sock->sk->sk_family; |
4214 | else | 4214 | else |
4215 | goto out; | 4215 | goto out; |
4216 | 4216 | ||
4217 | if (sock && family == PF_UNIX) | 4217 | if (sock && family == PF_UNIX) |
4218 | selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid); | 4218 | selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid); |
4219 | else if (skb) | 4219 | else if (skb) |
4220 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); | 4220 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); |
4221 | 4221 | ||
4222 | out: | 4222 | out: |
4223 | *secid = peer_secid; | 4223 | *secid = peer_secid; |
4224 | if (peer_secid == SECSID_NULL) | 4224 | if (peer_secid == SECSID_NULL) |
4225 | return -EINVAL; | 4225 | return -EINVAL; |
4226 | return 0; | 4226 | return 0; |
4227 | } | 4227 | } |
4228 | 4228 | ||
4229 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4229 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4230 | { | 4230 | { |
4231 | struct sk_security_struct *sksec; | 4231 | struct sk_security_struct *sksec; |
4232 | 4232 | ||
4233 | sksec = kzalloc(sizeof(*sksec), priority); | 4233 | sksec = kzalloc(sizeof(*sksec), priority); |
4234 | if (!sksec) | 4234 | if (!sksec) |
4235 | return -ENOMEM; | 4235 | return -ENOMEM; |
4236 | 4236 | ||
4237 | sksec->peer_sid = SECINITSID_UNLABELED; | 4237 | sksec->peer_sid = SECINITSID_UNLABELED; |
4238 | sksec->sid = SECINITSID_UNLABELED; | 4238 | sksec->sid = SECINITSID_UNLABELED; |
4239 | selinux_netlbl_sk_security_reset(sksec); | 4239 | selinux_netlbl_sk_security_reset(sksec); |
4240 | sk->sk_security = sksec; | 4240 | sk->sk_security = sksec; |
4241 | 4241 | ||
4242 | return 0; | 4242 | return 0; |
4243 | } | 4243 | } |
4244 | 4244 | ||
4245 | static void selinux_sk_free_security(struct sock *sk) | 4245 | static void selinux_sk_free_security(struct sock *sk) |
4246 | { | 4246 | { |
4247 | struct sk_security_struct *sksec = sk->sk_security; | 4247 | struct sk_security_struct *sksec = sk->sk_security; |
4248 | 4248 | ||
4249 | sk->sk_security = NULL; | 4249 | sk->sk_security = NULL; |
4250 | selinux_netlbl_sk_security_free(sksec); | 4250 | selinux_netlbl_sk_security_free(sksec); |
4251 | kfree(sksec); | 4251 | kfree(sksec); |
4252 | } | 4252 | } |
4253 | 4253 | ||
4254 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4254 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
4255 | { | 4255 | { |
4256 | struct sk_security_struct *sksec = sk->sk_security; | 4256 | struct sk_security_struct *sksec = sk->sk_security; |
4257 | struct sk_security_struct *newsksec = newsk->sk_security; | 4257 | struct sk_security_struct *newsksec = newsk->sk_security; |
4258 | 4258 | ||
4259 | newsksec->sid = sksec->sid; | 4259 | newsksec->sid = sksec->sid; |
4260 | newsksec->peer_sid = sksec->peer_sid; | 4260 | newsksec->peer_sid = sksec->peer_sid; |
4261 | newsksec->sclass = sksec->sclass; | 4261 | newsksec->sclass = sksec->sclass; |
4262 | 4262 | ||
4263 | selinux_netlbl_sk_security_reset(newsksec); | 4263 | selinux_netlbl_sk_security_reset(newsksec); |
4264 | } | 4264 | } |
4265 | 4265 | ||
4266 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4266 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
4267 | { | 4267 | { |
4268 | if (!sk) | 4268 | if (!sk) |
4269 | *secid = SECINITSID_ANY_SOCKET; | 4269 | *secid = SECINITSID_ANY_SOCKET; |
4270 | else { | 4270 | else { |
4271 | struct sk_security_struct *sksec = sk->sk_security; | 4271 | struct sk_security_struct *sksec = sk->sk_security; |
4272 | 4272 | ||
4273 | *secid = sksec->sid; | 4273 | *secid = sksec->sid; |
4274 | } | 4274 | } |
4275 | } | 4275 | } |
4276 | 4276 | ||
4277 | static void selinux_sock_graft(struct sock *sk, struct socket *parent) | 4277 | static void selinux_sock_graft(struct sock *sk, struct socket *parent) |
4278 | { | 4278 | { |
4279 | struct inode_security_struct *isec = SOCK_INODE(parent)->i_security; | 4279 | struct inode_security_struct *isec = SOCK_INODE(parent)->i_security; |
4280 | struct sk_security_struct *sksec = sk->sk_security; | 4280 | struct sk_security_struct *sksec = sk->sk_security; |
4281 | 4281 | ||
4282 | if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || | 4282 | if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || |
4283 | sk->sk_family == PF_UNIX) | 4283 | sk->sk_family == PF_UNIX) |
4284 | isec->sid = sksec->sid; | 4284 | isec->sid = sksec->sid; |
4285 | sksec->sclass = isec->sclass; | 4285 | sksec->sclass = isec->sclass; |
4286 | } | 4286 | } |
4287 | 4287 | ||
4288 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 4288 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
4289 | struct request_sock *req) | 4289 | struct request_sock *req) |
4290 | { | 4290 | { |
4291 | struct sk_security_struct *sksec = sk->sk_security; | 4291 | struct sk_security_struct *sksec = sk->sk_security; |
4292 | int err; | 4292 | int err; |
4293 | u16 family = sk->sk_family; | 4293 | u16 family = sk->sk_family; |
4294 | u32 newsid; | 4294 | u32 newsid; |
4295 | u32 peersid; | 4295 | u32 peersid; |
4296 | 4296 | ||
4297 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 4297 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
4298 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 4298 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
4299 | family = PF_INET; | 4299 | family = PF_INET; |
4300 | 4300 | ||
4301 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); | 4301 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); |
4302 | if (err) | 4302 | if (err) |
4303 | return err; | 4303 | return err; |
4304 | if (peersid == SECSID_NULL) { | 4304 | if (peersid == SECSID_NULL) { |
4305 | req->secid = sksec->sid; | 4305 | req->secid = sksec->sid; |
4306 | req->peer_secid = SECSID_NULL; | 4306 | req->peer_secid = SECSID_NULL; |
4307 | } else { | 4307 | } else { |
4308 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); | 4308 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); |
4309 | if (err) | 4309 | if (err) |
4310 | return err; | 4310 | return err; |
4311 | req->secid = newsid; | 4311 | req->secid = newsid; |
4312 | req->peer_secid = peersid; | 4312 | req->peer_secid = peersid; |
4313 | } | 4313 | } |
4314 | 4314 | ||
4315 | return selinux_netlbl_inet_conn_request(req, family); | 4315 | return selinux_netlbl_inet_conn_request(req, family); |
4316 | } | 4316 | } |
4317 | 4317 | ||
4318 | static void selinux_inet_csk_clone(struct sock *newsk, | 4318 | static void selinux_inet_csk_clone(struct sock *newsk, |
4319 | const struct request_sock *req) | 4319 | const struct request_sock *req) |
4320 | { | 4320 | { |
4321 | struct sk_security_struct *newsksec = newsk->sk_security; | 4321 | struct sk_security_struct *newsksec = newsk->sk_security; |
4322 | 4322 | ||
4323 | newsksec->sid = req->secid; | 4323 | newsksec->sid = req->secid; |
4324 | newsksec->peer_sid = req->peer_secid; | 4324 | newsksec->peer_sid = req->peer_secid; |
4325 | /* NOTE: Ideally, we should also get the isec->sid for the | 4325 | /* NOTE: Ideally, we should also get the isec->sid for the |
4326 | new socket in sync, but we don't have the isec available yet. | 4326 | new socket in sync, but we don't have the isec available yet. |
4327 | So we will wait until sock_graft to do it, by which | 4327 | So we will wait until sock_graft to do it, by which |
4328 | time it will have been created and available. */ | 4328 | time it will have been created and available. */ |
4329 | 4329 | ||
4330 | /* We don't need to take any sort of lock here as we are the only | 4330 | /* We don't need to take any sort of lock here as we are the only |
4331 | * thread with access to newsksec */ | 4331 | * thread with access to newsksec */ |
4332 | selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family); | 4332 | selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family); |
4333 | } | 4333 | } |
4334 | 4334 | ||
4335 | static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | 4335 | static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) |
4336 | { | 4336 | { |
4337 | u16 family = sk->sk_family; | 4337 | u16 family = sk->sk_family; |
4338 | struct sk_security_struct *sksec = sk->sk_security; | 4338 | struct sk_security_struct *sksec = sk->sk_security; |
4339 | 4339 | ||
4340 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 4340 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
4341 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 4341 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
4342 | family = PF_INET; | 4342 | family = PF_INET; |
4343 | 4343 | ||
4344 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | 4344 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); |
4345 | } | 4345 | } |
4346 | 4346 | ||
4347 | static int selinux_secmark_relabel_packet(u32 sid) | 4347 | static int selinux_secmark_relabel_packet(u32 sid) |
4348 | { | 4348 | { |
4349 | const struct task_security_struct *__tsec; | 4349 | const struct task_security_struct *__tsec; |
4350 | u32 tsid; | 4350 | u32 tsid; |
4351 | 4351 | ||
4352 | __tsec = current_security(); | 4352 | __tsec = current_security(); |
4353 | tsid = __tsec->sid; | 4353 | tsid = __tsec->sid; |
4354 | 4354 | ||
4355 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); | 4355 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); |
4356 | } | 4356 | } |
4357 | 4357 | ||
4358 | static void selinux_secmark_refcount_inc(void) | 4358 | static void selinux_secmark_refcount_inc(void) |
4359 | { | 4359 | { |
4360 | atomic_inc(&selinux_secmark_refcount); | 4360 | atomic_inc(&selinux_secmark_refcount); |
4361 | } | 4361 | } |
4362 | 4362 | ||
4363 | static void selinux_secmark_refcount_dec(void) | 4363 | static void selinux_secmark_refcount_dec(void) |
4364 | { | 4364 | { |
4365 | atomic_dec(&selinux_secmark_refcount); | 4365 | atomic_dec(&selinux_secmark_refcount); |
4366 | } | 4366 | } |
4367 | 4367 | ||
4368 | static void selinux_req_classify_flow(const struct request_sock *req, | 4368 | static void selinux_req_classify_flow(const struct request_sock *req, |
4369 | struct flowi *fl) | 4369 | struct flowi *fl) |
4370 | { | 4370 | { |
4371 | fl->flowi_secid = req->secid; | 4371 | fl->flowi_secid = req->secid; |
4372 | } | 4372 | } |
4373 | 4373 | ||
4374 | static int selinux_tun_dev_create(void) | 4374 | static int selinux_tun_dev_create(void) |
4375 | { | 4375 | { |
4376 | u32 sid = current_sid(); | 4376 | u32 sid = current_sid(); |
4377 | 4377 | ||
4378 | /* we aren't taking into account the "sockcreate" SID since the socket | 4378 | /* we aren't taking into account the "sockcreate" SID since the socket |
4379 | * that is being created here is not a socket in the traditional sense, | 4379 | * that is being created here is not a socket in the traditional sense, |
4380 | * instead it is a private sock, accessible only to the kernel, and | 4380 | * instead it is a private sock, accessible only to the kernel, and |
4381 | * representing a wide range of network traffic spanning multiple | 4381 | * representing a wide range of network traffic spanning multiple |
4382 | * connections unlike traditional sockets - check the TUN driver to | 4382 | * connections unlike traditional sockets - check the TUN driver to |
4383 | * get a better understanding of why this socket is special */ | 4383 | * get a better understanding of why this socket is special */ |
4384 | 4384 | ||
4385 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | 4385 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, |
4386 | NULL); | 4386 | NULL); |
4387 | } | 4387 | } |
4388 | 4388 | ||
4389 | static void selinux_tun_dev_post_create(struct sock *sk) | 4389 | static void selinux_tun_dev_post_create(struct sock *sk) |
4390 | { | 4390 | { |
4391 | struct sk_security_struct *sksec = sk->sk_security; | 4391 | struct sk_security_struct *sksec = sk->sk_security; |
4392 | 4392 | ||
4393 | /* we don't currently perform any NetLabel based labeling here and it | 4393 | /* we don't currently perform any NetLabel based labeling here and it |
4394 | * isn't clear that we would want to do so anyway; while we could apply | 4394 | * isn't clear that we would want to do so anyway; while we could apply |
4395 | * labeling without the support of the TUN user the resulting labeled | 4395 | * labeling without the support of the TUN user the resulting labeled |
4396 | * traffic from the other end of the connection would almost certainly | 4396 | * traffic from the other end of the connection would almost certainly |
4397 | * cause confusion to the TUN user that had no idea network labeling | 4397 | * cause confusion to the TUN user that had no idea network labeling |
4398 | * protocols were being used */ | 4398 | * protocols were being used */ |
4399 | 4399 | ||
4400 | /* see the comments in selinux_tun_dev_create() about why we don't use | 4400 | /* see the comments in selinux_tun_dev_create() about why we don't use |
4401 | * the sockcreate SID here */ | 4401 | * the sockcreate SID here */ |
4402 | 4402 | ||
4403 | sksec->sid = current_sid(); | 4403 | sksec->sid = current_sid(); |
4404 | sksec->sclass = SECCLASS_TUN_SOCKET; | 4404 | sksec->sclass = SECCLASS_TUN_SOCKET; |
4405 | } | 4405 | } |
4406 | 4406 | ||
4407 | static int selinux_tun_dev_attach(struct sock *sk) | 4407 | static int selinux_tun_dev_attach(struct sock *sk) |
4408 | { | 4408 | { |
4409 | struct sk_security_struct *sksec = sk->sk_security; | 4409 | struct sk_security_struct *sksec = sk->sk_security; |
4410 | u32 sid = current_sid(); | 4410 | u32 sid = current_sid(); |
4411 | int err; | 4411 | int err; |
4412 | 4412 | ||
4413 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | 4413 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, |
4414 | TUN_SOCKET__RELABELFROM, NULL); | 4414 | TUN_SOCKET__RELABELFROM, NULL); |
4415 | if (err) | 4415 | if (err) |
4416 | return err; | 4416 | return err; |
4417 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | 4417 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, |
4418 | TUN_SOCKET__RELABELTO, NULL); | 4418 | TUN_SOCKET__RELABELTO, NULL); |
4419 | if (err) | 4419 | if (err) |
4420 | return err; | 4420 | return err; |
4421 | 4421 | ||
4422 | sksec->sid = sid; | 4422 | sksec->sid = sid; |
4423 | 4423 | ||
4424 | return 0; | 4424 | return 0; |
4425 | } | 4425 | } |
4426 | 4426 | ||
4427 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4427 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
4428 | { | 4428 | { |
4429 | int err = 0; | 4429 | int err = 0; |
4430 | u32 perm; | 4430 | u32 perm; |
4431 | struct nlmsghdr *nlh; | 4431 | struct nlmsghdr *nlh; |
4432 | struct sk_security_struct *sksec = sk->sk_security; | 4432 | struct sk_security_struct *sksec = sk->sk_security; |
4433 | 4433 | ||
4434 | if (skb->len < NLMSG_SPACE(0)) { | 4434 | if (skb->len < NLMSG_SPACE(0)) { |
4435 | err = -EINVAL; | 4435 | err = -EINVAL; |
4436 | goto out; | 4436 | goto out; |
4437 | } | 4437 | } |
4438 | nlh = nlmsg_hdr(skb); | 4438 | nlh = nlmsg_hdr(skb); |
4439 | 4439 | ||
4440 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); | 4440 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4441 | if (err) { | 4441 | if (err) { |
4442 | if (err == -EINVAL) { | 4442 | if (err == -EINVAL) { |
4443 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4443 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4444 | "SELinux: unrecognized netlink message" | 4444 | "SELinux: unrecognized netlink message" |
4445 | " type=%hu for sclass=%hu\n", | 4445 | " type=%hu for sclass=%hu\n", |
4446 | nlh->nlmsg_type, sksec->sclass); | 4446 | nlh->nlmsg_type, sksec->sclass); |
4447 | if (!selinux_enforcing || security_get_allow_unknown()) | 4447 | if (!selinux_enforcing || security_get_allow_unknown()) |
4448 | err = 0; | 4448 | err = 0; |
4449 | } | 4449 | } |
4450 | 4450 | ||
4451 | /* Ignore */ | 4451 | /* Ignore */ |
4452 | if (err == -ENOENT) | 4452 | if (err == -ENOENT) |
4453 | err = 0; | 4453 | err = 0; |
4454 | goto out; | 4454 | goto out; |
4455 | } | 4455 | } |
4456 | 4456 | ||
4457 | err = sock_has_perm(current, sk, perm); | 4457 | err = sock_has_perm(current, sk, perm); |
4458 | out: | 4458 | out: |
4459 | return err; | 4459 | return err; |
4460 | } | 4460 | } |
4461 | 4461 | ||
4462 | #ifdef CONFIG_NETFILTER | 4462 | #ifdef CONFIG_NETFILTER |
4463 | 4463 | ||
4464 | static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | 4464 | static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, |
4465 | u16 family) | 4465 | u16 family) |
4466 | { | 4466 | { |
4467 | int err; | 4467 | int err; |
4468 | char *addrp; | 4468 | char *addrp; |
4469 | u32 peer_sid; | 4469 | u32 peer_sid; |
4470 | struct common_audit_data ad; | 4470 | struct common_audit_data ad; |
4471 | u8 secmark_active; | 4471 | u8 secmark_active; |
4472 | u8 netlbl_active; | 4472 | u8 netlbl_active; |
4473 | u8 peerlbl_active; | 4473 | u8 peerlbl_active; |
4474 | 4474 | ||
4475 | if (!selinux_policycap_netpeer) | 4475 | if (!selinux_policycap_netpeer) |
4476 | return NF_ACCEPT; | 4476 | return NF_ACCEPT; |
4477 | 4477 | ||
4478 | secmark_active = selinux_secmark_enabled(); | 4478 | secmark_active = selinux_secmark_enabled(); |
4479 | netlbl_active = netlbl_enabled(); | 4479 | netlbl_active = netlbl_enabled(); |
4480 | peerlbl_active = netlbl_active || selinux_xfrm_enabled(); | 4480 | peerlbl_active = netlbl_active || selinux_xfrm_enabled(); |
4481 | if (!secmark_active && !peerlbl_active) | 4481 | if (!secmark_active && !peerlbl_active) |
4482 | return NF_ACCEPT; | 4482 | return NF_ACCEPT; |
4483 | 4483 | ||
4484 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4484 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4485 | return NF_DROP; | 4485 | return NF_DROP; |
4486 | 4486 | ||
4487 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4487 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4488 | ad.u.net.netif = ifindex; | 4488 | ad.u.net.netif = ifindex; |
4489 | ad.u.net.family = family; | 4489 | ad.u.net.family = family; |
4490 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4490 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
4491 | return NF_DROP; | 4491 | return NF_DROP; |
4492 | 4492 | ||
4493 | if (peerlbl_active) { | 4493 | if (peerlbl_active) { |
4494 | err = selinux_inet_sys_rcv_skb(ifindex, addrp, family, | 4494 | err = selinux_inet_sys_rcv_skb(ifindex, addrp, family, |
4495 | peer_sid, &ad); | 4495 | peer_sid, &ad); |
4496 | if (err) { | 4496 | if (err) { |
4497 | selinux_netlbl_err(skb, err, 1); | 4497 | selinux_netlbl_err(skb, err, 1); |
4498 | return NF_DROP; | 4498 | return NF_DROP; |
4499 | } | 4499 | } |
4500 | } | 4500 | } |
4501 | 4501 | ||
4502 | if (secmark_active) | 4502 | if (secmark_active) |
4503 | if (avc_has_perm(peer_sid, skb->secmark, | 4503 | if (avc_has_perm(peer_sid, skb->secmark, |
4504 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) | 4504 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) |
4505 | return NF_DROP; | 4505 | return NF_DROP; |
4506 | 4506 | ||
4507 | if (netlbl_active) | 4507 | if (netlbl_active) |
4508 | /* we do this in the FORWARD path and not the POST_ROUTING | 4508 | /* we do this in the FORWARD path and not the POST_ROUTING |
4509 | * path because we want to make sure we apply the necessary | 4509 | * path because we want to make sure we apply the necessary |
4510 | * labeling before IPsec is applied so we can leverage AH | 4510 | * labeling before IPsec is applied so we can leverage AH |
4511 | * protection */ | 4511 | * protection */ |
4512 | if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0) | 4512 | if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0) |
4513 | return NF_DROP; | 4513 | return NF_DROP; |
4514 | 4514 | ||
4515 | return NF_ACCEPT; | 4515 | return NF_ACCEPT; |
4516 | } | 4516 | } |
4517 | 4517 | ||
4518 | static unsigned int selinux_ipv4_forward(unsigned int hooknum, | 4518 | static unsigned int selinux_ipv4_forward(unsigned int hooknum, |
4519 | struct sk_buff *skb, | 4519 | struct sk_buff *skb, |
4520 | const struct net_device *in, | 4520 | const struct net_device *in, |
4521 | const struct net_device *out, | 4521 | const struct net_device *out, |
4522 | int (*okfn)(struct sk_buff *)) | 4522 | int (*okfn)(struct sk_buff *)) |
4523 | { | 4523 | { |
4524 | return selinux_ip_forward(skb, in->ifindex, PF_INET); | 4524 | return selinux_ip_forward(skb, in->ifindex, PF_INET); |
4525 | } | 4525 | } |
4526 | 4526 | ||
4527 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4527 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
4528 | static unsigned int selinux_ipv6_forward(unsigned int hooknum, | 4528 | static unsigned int selinux_ipv6_forward(unsigned int hooknum, |
4529 | struct sk_buff *skb, | 4529 | struct sk_buff *skb, |
4530 | const struct net_device *in, | 4530 | const struct net_device *in, |
4531 | const struct net_device *out, | 4531 | const struct net_device *out, |
4532 | int (*okfn)(struct sk_buff *)) | 4532 | int (*okfn)(struct sk_buff *)) |
4533 | { | 4533 | { |
4534 | return selinux_ip_forward(skb, in->ifindex, PF_INET6); | 4534 | return selinux_ip_forward(skb, in->ifindex, PF_INET6); |
4535 | } | 4535 | } |
4536 | #endif /* IPV6 */ | 4536 | #endif /* IPV6 */ |
4537 | 4537 | ||
4538 | static unsigned int selinux_ip_output(struct sk_buff *skb, | 4538 | static unsigned int selinux_ip_output(struct sk_buff *skb, |
4539 | u16 family) | 4539 | u16 family) |
4540 | { | 4540 | { |
4541 | u32 sid; | 4541 | u32 sid; |
4542 | 4542 | ||
4543 | if (!netlbl_enabled()) | 4543 | if (!netlbl_enabled()) |
4544 | return NF_ACCEPT; | 4544 | return NF_ACCEPT; |
4545 | 4545 | ||
4546 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path | 4546 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path |
4547 | * because we want to make sure we apply the necessary labeling | 4547 | * because we want to make sure we apply the necessary labeling |
4548 | * before IPsec is applied so we can leverage AH protection */ | 4548 | * before IPsec is applied so we can leverage AH protection */ |
4549 | if (skb->sk) { | 4549 | if (skb->sk) { |
4550 | struct sk_security_struct *sksec = skb->sk->sk_security; | 4550 | struct sk_security_struct *sksec = skb->sk->sk_security; |
4551 | sid = sksec->sid; | 4551 | sid = sksec->sid; |
4552 | } else | 4552 | } else |
4553 | sid = SECINITSID_KERNEL; | 4553 | sid = SECINITSID_KERNEL; |
4554 | if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0) | 4554 | if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0) |
4555 | return NF_DROP; | 4555 | return NF_DROP; |
4556 | 4556 | ||
4557 | return NF_ACCEPT; | 4557 | return NF_ACCEPT; |
4558 | } | 4558 | } |
4559 | 4559 | ||
4560 | static unsigned int selinux_ipv4_output(unsigned int hooknum, | 4560 | static unsigned int selinux_ipv4_output(unsigned int hooknum, |
4561 | struct sk_buff *skb, | 4561 | struct sk_buff *skb, |
4562 | const struct net_device *in, | 4562 | const struct net_device *in, |
4563 | const struct net_device *out, | 4563 | const struct net_device *out, |
4564 | int (*okfn)(struct sk_buff *)) | 4564 | int (*okfn)(struct sk_buff *)) |
4565 | { | 4565 | { |
4566 | return selinux_ip_output(skb, PF_INET); | 4566 | return selinux_ip_output(skb, PF_INET); |
4567 | } | 4567 | } |
4568 | 4568 | ||
4569 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | 4569 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, |
4570 | int ifindex, | 4570 | int ifindex, |
4571 | u16 family) | 4571 | u16 family) |
4572 | { | 4572 | { |
4573 | struct sock *sk = skb->sk; | 4573 | struct sock *sk = skb->sk; |
4574 | struct sk_security_struct *sksec; | 4574 | struct sk_security_struct *sksec; |
4575 | struct common_audit_data ad; | 4575 | struct common_audit_data ad; |
4576 | char *addrp; | 4576 | char *addrp; |
4577 | u8 proto; | 4577 | u8 proto; |
4578 | 4578 | ||
4579 | if (sk == NULL) | 4579 | if (sk == NULL) |
4580 | return NF_ACCEPT; | 4580 | return NF_ACCEPT; |
4581 | sksec = sk->sk_security; | 4581 | sksec = sk->sk_security; |
4582 | 4582 | ||
4583 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4583 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4584 | ad.u.net.netif = ifindex; | 4584 | ad.u.net.netif = ifindex; |
4585 | ad.u.net.family = family; | 4585 | ad.u.net.family = family; |
4586 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4586 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
4587 | return NF_DROP; | 4587 | return NF_DROP; |
4588 | 4588 | ||
4589 | if (selinux_secmark_enabled()) | 4589 | if (selinux_secmark_enabled()) |
4590 | if (avc_has_perm(sksec->sid, skb->secmark, | 4590 | if (avc_has_perm(sksec->sid, skb->secmark, |
4591 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 4591 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4592 | return NF_DROP_ERR(-ECONNREFUSED); | 4592 | return NF_DROP_ERR(-ECONNREFUSED); |
4593 | 4593 | ||
4594 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | 4594 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4595 | return NF_DROP_ERR(-ECONNREFUSED); | 4595 | return NF_DROP_ERR(-ECONNREFUSED); |
4596 | 4596 | ||
4597 | return NF_ACCEPT; | 4597 | return NF_ACCEPT; |
4598 | } | 4598 | } |
4599 | 4599 | ||
4600 | static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | 4600 | static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, |
4601 | u16 family) | 4601 | u16 family) |
4602 | { | 4602 | { |
4603 | u32 secmark_perm; | 4603 | u32 secmark_perm; |
4604 | u32 peer_sid; | 4604 | u32 peer_sid; |
4605 | struct sock *sk; | 4605 | struct sock *sk; |
4606 | struct common_audit_data ad; | 4606 | struct common_audit_data ad; |
4607 | char *addrp; | 4607 | char *addrp; |
4608 | u8 secmark_active; | 4608 | u8 secmark_active; |
4609 | u8 peerlbl_active; | 4609 | u8 peerlbl_active; |
4610 | 4610 | ||
4611 | /* If any sort of compatibility mode is enabled then handoff processing | 4611 | /* If any sort of compatibility mode is enabled then handoff processing |
4612 | * to the selinux_ip_postroute_compat() function to deal with the | 4612 | * to the selinux_ip_postroute_compat() function to deal with the |
4613 | * special handling. We do this in an attempt to keep this function | 4613 | * special handling. We do this in an attempt to keep this function |
4614 | * as fast and as clean as possible. */ | 4614 | * as fast and as clean as possible. */ |
4615 | if (!selinux_policycap_netpeer) | 4615 | if (!selinux_policycap_netpeer) |
4616 | return selinux_ip_postroute_compat(skb, ifindex, family); | 4616 | return selinux_ip_postroute_compat(skb, ifindex, family); |
4617 | #ifdef CONFIG_XFRM | 4617 | #ifdef CONFIG_XFRM |
4618 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec | 4618 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec |
4619 | * packet transformation so allow the packet to pass without any checks | 4619 | * packet transformation so allow the packet to pass without any checks |
4620 | * since we'll have another chance to perform access control checks | 4620 | * since we'll have another chance to perform access control checks |
4621 | * when the packet is on it's final way out. | 4621 | * when the packet is on it's final way out. |
4622 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst | 4622 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst |
4623 | * is NULL, in this case go ahead and apply access control. */ | 4623 | * is NULL, in this case go ahead and apply access control. */ |
4624 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) | 4624 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) |
4625 | return NF_ACCEPT; | 4625 | return NF_ACCEPT; |
4626 | #endif | 4626 | #endif |
4627 | secmark_active = selinux_secmark_enabled(); | 4627 | secmark_active = selinux_secmark_enabled(); |
4628 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); | 4628 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); |
4629 | if (!secmark_active && !peerlbl_active) | 4629 | if (!secmark_active && !peerlbl_active) |
4630 | return NF_ACCEPT; | 4630 | return NF_ACCEPT; |
4631 | 4631 | ||
4632 | /* if the packet is being forwarded then get the peer label from the | 4632 | /* if the packet is being forwarded then get the peer label from the |
4633 | * packet itself; otherwise check to see if it is from a local | 4633 | * packet itself; otherwise check to see if it is from a local |
4634 | * application or the kernel, if from an application get the peer label | 4634 | * application or the kernel, if from an application get the peer label |
4635 | * from the sending socket, otherwise use the kernel's sid */ | 4635 | * from the sending socket, otherwise use the kernel's sid */ |
4636 | sk = skb->sk; | 4636 | sk = skb->sk; |
4637 | if (sk == NULL) { | 4637 | if (sk == NULL) { |
4638 | if (skb->skb_iif) { | 4638 | if (skb->skb_iif) { |
4639 | secmark_perm = PACKET__FORWARD_OUT; | 4639 | secmark_perm = PACKET__FORWARD_OUT; |
4640 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4640 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
4641 | return NF_DROP; | 4641 | return NF_DROP; |
4642 | } else { | 4642 | } else { |
4643 | secmark_perm = PACKET__SEND; | 4643 | secmark_perm = PACKET__SEND; |
4644 | peer_sid = SECINITSID_KERNEL; | 4644 | peer_sid = SECINITSID_KERNEL; |
4645 | } | 4645 | } |
4646 | } else { | 4646 | } else { |
4647 | struct sk_security_struct *sksec = sk->sk_security; | 4647 | struct sk_security_struct *sksec = sk->sk_security; |
4648 | peer_sid = sksec->sid; | 4648 | peer_sid = sksec->sid; |
4649 | secmark_perm = PACKET__SEND; | 4649 | secmark_perm = PACKET__SEND; |
4650 | } | 4650 | } |
4651 | 4651 | ||
4652 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4652 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4653 | ad.u.net.netif = ifindex; | 4653 | ad.u.net.netif = ifindex; |
4654 | ad.u.net.family = family; | 4654 | ad.u.net.family = family; |
4655 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4655 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
4656 | return NF_DROP; | 4656 | return NF_DROP; |
4657 | 4657 | ||
4658 | if (secmark_active) | 4658 | if (secmark_active) |
4659 | if (avc_has_perm(peer_sid, skb->secmark, | 4659 | if (avc_has_perm(peer_sid, skb->secmark, |
4660 | SECCLASS_PACKET, secmark_perm, &ad)) | 4660 | SECCLASS_PACKET, secmark_perm, &ad)) |
4661 | return NF_DROP_ERR(-ECONNREFUSED); | 4661 | return NF_DROP_ERR(-ECONNREFUSED); |
4662 | 4662 | ||
4663 | if (peerlbl_active) { | 4663 | if (peerlbl_active) { |
4664 | u32 if_sid; | 4664 | u32 if_sid; |
4665 | u32 node_sid; | 4665 | u32 node_sid; |
4666 | 4666 | ||
4667 | if (sel_netif_sid(ifindex, &if_sid)) | 4667 | if (sel_netif_sid(ifindex, &if_sid)) |
4668 | return NF_DROP; | 4668 | return NF_DROP; |
4669 | if (avc_has_perm(peer_sid, if_sid, | 4669 | if (avc_has_perm(peer_sid, if_sid, |
4670 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 4670 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
4671 | return NF_DROP_ERR(-ECONNREFUSED); | 4671 | return NF_DROP_ERR(-ECONNREFUSED); |
4672 | 4672 | ||
4673 | if (sel_netnode_sid(addrp, family, &node_sid)) | 4673 | if (sel_netnode_sid(addrp, family, &node_sid)) |
4674 | return NF_DROP; | 4674 | return NF_DROP; |
4675 | if (avc_has_perm(peer_sid, node_sid, | 4675 | if (avc_has_perm(peer_sid, node_sid, |
4676 | SECCLASS_NODE, NODE__SENDTO, &ad)) | 4676 | SECCLASS_NODE, NODE__SENDTO, &ad)) |
4677 | return NF_DROP_ERR(-ECONNREFUSED); | 4677 | return NF_DROP_ERR(-ECONNREFUSED); |
4678 | } | 4678 | } |
4679 | 4679 | ||
4680 | return NF_ACCEPT; | 4680 | return NF_ACCEPT; |
4681 | } | 4681 | } |
4682 | 4682 | ||
4683 | static unsigned int selinux_ipv4_postroute(unsigned int hooknum, | 4683 | static unsigned int selinux_ipv4_postroute(unsigned int hooknum, |
4684 | struct sk_buff *skb, | 4684 | struct sk_buff *skb, |
4685 | const struct net_device *in, | 4685 | const struct net_device *in, |
4686 | const struct net_device *out, | 4686 | const struct net_device *out, |
4687 | int (*okfn)(struct sk_buff *)) | 4687 | int (*okfn)(struct sk_buff *)) |
4688 | { | 4688 | { |
4689 | return selinux_ip_postroute(skb, out->ifindex, PF_INET); | 4689 | return selinux_ip_postroute(skb, out->ifindex, PF_INET); |
4690 | } | 4690 | } |
4691 | 4691 | ||
4692 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4692 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
4693 | static unsigned int selinux_ipv6_postroute(unsigned int hooknum, | 4693 | static unsigned int selinux_ipv6_postroute(unsigned int hooknum, |
4694 | struct sk_buff *skb, | 4694 | struct sk_buff *skb, |
4695 | const struct net_device *in, | 4695 | const struct net_device *in, |
4696 | const struct net_device *out, | 4696 | const struct net_device *out, |
4697 | int (*okfn)(struct sk_buff *)) | 4697 | int (*okfn)(struct sk_buff *)) |
4698 | { | 4698 | { |
4699 | return selinux_ip_postroute(skb, out->ifindex, PF_INET6); | 4699 | return selinux_ip_postroute(skb, out->ifindex, PF_INET6); |
4700 | } | 4700 | } |
4701 | #endif /* IPV6 */ | 4701 | #endif /* IPV6 */ |
4702 | 4702 | ||
4703 | #endif /* CONFIG_NETFILTER */ | 4703 | #endif /* CONFIG_NETFILTER */ |
4704 | 4704 | ||
4705 | static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | 4705 | static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) |
4706 | { | 4706 | { |
4707 | int err; | 4707 | int err; |
4708 | 4708 | ||
4709 | err = cap_netlink_send(sk, skb); | 4709 | err = cap_netlink_send(sk, skb); |
4710 | if (err) | 4710 | if (err) |
4711 | return err; | 4711 | return err; |
4712 | 4712 | ||
4713 | return selinux_nlmsg_perm(sk, skb); | 4713 | return selinux_nlmsg_perm(sk, skb); |
4714 | } | 4714 | } |
4715 | 4715 | ||
4716 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | ||
4717 | { | ||
4718 | int err; | ||
4719 | struct common_audit_data ad; | ||
4720 | u32 sid; | ||
4721 | |||
4722 | err = cap_netlink_recv(skb, capability); | ||
4723 | if (err) | ||
4724 | return err; | ||
4725 | |||
4726 | COMMON_AUDIT_DATA_INIT(&ad, CAP); | ||
4727 | ad.u.cap = capability; | ||
4728 | |||
4729 | security_task_getsecid(current, &sid); | ||
4730 | return avc_has_perm(sid, sid, SECCLASS_CAPABILITY, | ||
4731 | CAP_TO_MASK(capability), &ad); | ||
4732 | } | ||
4733 | |||
4734 | static int ipc_alloc_security(struct task_struct *task, | 4716 | static int ipc_alloc_security(struct task_struct *task, |
4735 | struct kern_ipc_perm *perm, | 4717 | struct kern_ipc_perm *perm, |
4736 | u16 sclass) | 4718 | u16 sclass) |
4737 | { | 4719 | { |
4738 | struct ipc_security_struct *isec; | 4720 | struct ipc_security_struct *isec; |
4739 | u32 sid; | 4721 | u32 sid; |
4740 | 4722 | ||
4741 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); | 4723 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); |
4742 | if (!isec) | 4724 | if (!isec) |
4743 | return -ENOMEM; | 4725 | return -ENOMEM; |
4744 | 4726 | ||
4745 | sid = task_sid(task); | 4727 | sid = task_sid(task); |
4746 | isec->sclass = sclass; | 4728 | isec->sclass = sclass; |
4747 | isec->sid = sid; | 4729 | isec->sid = sid; |
4748 | perm->security = isec; | 4730 | perm->security = isec; |
4749 | 4731 | ||
4750 | return 0; | 4732 | return 0; |
4751 | } | 4733 | } |
4752 | 4734 | ||
4753 | static void ipc_free_security(struct kern_ipc_perm *perm) | 4735 | static void ipc_free_security(struct kern_ipc_perm *perm) |
4754 | { | 4736 | { |
4755 | struct ipc_security_struct *isec = perm->security; | 4737 | struct ipc_security_struct *isec = perm->security; |
4756 | perm->security = NULL; | 4738 | perm->security = NULL; |
4757 | kfree(isec); | 4739 | kfree(isec); |
4758 | } | 4740 | } |
4759 | 4741 | ||
4760 | static int msg_msg_alloc_security(struct msg_msg *msg) | 4742 | static int msg_msg_alloc_security(struct msg_msg *msg) |
4761 | { | 4743 | { |
4762 | struct msg_security_struct *msec; | 4744 | struct msg_security_struct *msec; |
4763 | 4745 | ||
4764 | msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL); | 4746 | msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL); |
4765 | if (!msec) | 4747 | if (!msec) |
4766 | return -ENOMEM; | 4748 | return -ENOMEM; |
4767 | 4749 | ||
4768 | msec->sid = SECINITSID_UNLABELED; | 4750 | msec->sid = SECINITSID_UNLABELED; |
4769 | msg->security = msec; | 4751 | msg->security = msec; |
4770 | 4752 | ||
4771 | return 0; | 4753 | return 0; |
4772 | } | 4754 | } |
4773 | 4755 | ||
4774 | static void msg_msg_free_security(struct msg_msg *msg) | 4756 | static void msg_msg_free_security(struct msg_msg *msg) |
4775 | { | 4757 | { |
4776 | struct msg_security_struct *msec = msg->security; | 4758 | struct msg_security_struct *msec = msg->security; |
4777 | 4759 | ||
4778 | msg->security = NULL; | 4760 | msg->security = NULL; |
4779 | kfree(msec); | 4761 | kfree(msec); |
4780 | } | 4762 | } |
4781 | 4763 | ||
4782 | static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | 4764 | static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, |
4783 | u32 perms) | 4765 | u32 perms) |
4784 | { | 4766 | { |
4785 | struct ipc_security_struct *isec; | 4767 | struct ipc_security_struct *isec; |
4786 | struct common_audit_data ad; | 4768 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4769 | u32 sid = current_sid(); |
4788 | 4770 | ||
4789 | isec = ipc_perms->security; | 4771 | isec = ipc_perms->security; |
4790 | 4772 | ||
4791 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4773 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4792 | ad.u.ipc_id = ipc_perms->key; | 4774 | ad.u.ipc_id = ipc_perms->key; |
4793 | 4775 | ||
4794 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4776 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
4795 | } | 4777 | } |
4796 | 4778 | ||
4797 | static int selinux_msg_msg_alloc_security(struct msg_msg *msg) | 4779 | static int selinux_msg_msg_alloc_security(struct msg_msg *msg) |
4798 | { | 4780 | { |
4799 | return msg_msg_alloc_security(msg); | 4781 | return msg_msg_alloc_security(msg); |
4800 | } | 4782 | } |
4801 | 4783 | ||
4802 | static void selinux_msg_msg_free_security(struct msg_msg *msg) | 4784 | static void selinux_msg_msg_free_security(struct msg_msg *msg) |
4803 | { | 4785 | { |
4804 | msg_msg_free_security(msg); | 4786 | msg_msg_free_security(msg); |
4805 | } | 4787 | } |
4806 | 4788 | ||
4807 | /* message queue security operations */ | 4789 | /* message queue security operations */ |
4808 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4790 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4809 | { | 4791 | { |
4810 | struct ipc_security_struct *isec; | 4792 | struct ipc_security_struct *isec; |
4811 | struct common_audit_data ad; | 4793 | struct common_audit_data ad; |
4812 | u32 sid = current_sid(); | 4794 | u32 sid = current_sid(); |
4813 | int rc; | 4795 | int rc; |
4814 | 4796 | ||
4815 | rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); | 4797 | rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); |
4816 | if (rc) | 4798 | if (rc) |
4817 | return rc; | 4799 | return rc; |
4818 | 4800 | ||
4819 | isec = msq->q_perm.security; | 4801 | isec = msq->q_perm.security; |
4820 | 4802 | ||
4821 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4803 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4822 | ad.u.ipc_id = msq->q_perm.key; | 4804 | ad.u.ipc_id = msq->q_perm.key; |
4823 | 4805 | ||
4824 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4806 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
4825 | MSGQ__CREATE, &ad); | 4807 | MSGQ__CREATE, &ad); |
4826 | if (rc) { | 4808 | if (rc) { |
4827 | ipc_free_security(&msq->q_perm); | 4809 | ipc_free_security(&msq->q_perm); |
4828 | return rc; | 4810 | return rc; |
4829 | } | 4811 | } |
4830 | return 0; | 4812 | return 0; |
4831 | } | 4813 | } |
4832 | 4814 | ||
4833 | static void selinux_msg_queue_free_security(struct msg_queue *msq) | 4815 | static void selinux_msg_queue_free_security(struct msg_queue *msq) |
4834 | { | 4816 | { |
4835 | ipc_free_security(&msq->q_perm); | 4817 | ipc_free_security(&msq->q_perm); |
4836 | } | 4818 | } |
4837 | 4819 | ||
4838 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4820 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4839 | { | 4821 | { |
4840 | struct ipc_security_struct *isec; | 4822 | struct ipc_security_struct *isec; |
4841 | struct common_audit_data ad; | 4823 | struct common_audit_data ad; |
4842 | u32 sid = current_sid(); | 4824 | u32 sid = current_sid(); |
4843 | 4825 | ||
4844 | isec = msq->q_perm.security; | 4826 | isec = msq->q_perm.security; |
4845 | 4827 | ||
4846 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4828 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4847 | ad.u.ipc_id = msq->q_perm.key; | 4829 | ad.u.ipc_id = msq->q_perm.key; |
4848 | 4830 | ||
4849 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4831 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
4850 | MSGQ__ASSOCIATE, &ad); | 4832 | MSGQ__ASSOCIATE, &ad); |
4851 | } | 4833 | } |
4852 | 4834 | ||
4853 | static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) | 4835 | static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) |
4854 | { | 4836 | { |
4855 | int err; | 4837 | int err; |
4856 | int perms; | 4838 | int perms; |
4857 | 4839 | ||
4858 | switch (cmd) { | 4840 | switch (cmd) { |
4859 | case IPC_INFO: | 4841 | case IPC_INFO: |
4860 | case MSG_INFO: | 4842 | case MSG_INFO: |
4861 | /* No specific object, just general system-wide information. */ | 4843 | /* No specific object, just general system-wide information. */ |
4862 | return task_has_system(current, SYSTEM__IPC_INFO); | 4844 | return task_has_system(current, SYSTEM__IPC_INFO); |
4863 | case IPC_STAT: | 4845 | case IPC_STAT: |
4864 | case MSG_STAT: | 4846 | case MSG_STAT: |
4865 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; | 4847 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; |
4866 | break; | 4848 | break; |
4867 | case IPC_SET: | 4849 | case IPC_SET: |
4868 | perms = MSGQ__SETATTR; | 4850 | perms = MSGQ__SETATTR; |
4869 | break; | 4851 | break; |
4870 | case IPC_RMID: | 4852 | case IPC_RMID: |
4871 | perms = MSGQ__DESTROY; | 4853 | perms = MSGQ__DESTROY; |
4872 | break; | 4854 | break; |
4873 | default: | 4855 | default: |
4874 | return 0; | 4856 | return 0; |
4875 | } | 4857 | } |
4876 | 4858 | ||
4877 | err = ipc_has_perm(&msq->q_perm, perms); | 4859 | err = ipc_has_perm(&msq->q_perm, perms); |
4878 | return err; | 4860 | return err; |
4879 | } | 4861 | } |
4880 | 4862 | ||
4881 | static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg) | 4863 | static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg) |
4882 | { | 4864 | { |
4883 | struct ipc_security_struct *isec; | 4865 | struct ipc_security_struct *isec; |
4884 | struct msg_security_struct *msec; | 4866 | struct msg_security_struct *msec; |
4885 | struct common_audit_data ad; | 4867 | struct common_audit_data ad; |
4886 | u32 sid = current_sid(); | 4868 | u32 sid = current_sid(); |
4887 | int rc; | 4869 | int rc; |
4888 | 4870 | ||
4889 | isec = msq->q_perm.security; | 4871 | isec = msq->q_perm.security; |
4890 | msec = msg->security; | 4872 | msec = msg->security; |
4891 | 4873 | ||
4892 | /* | 4874 | /* |
4893 | * First time through, need to assign label to the message | 4875 | * First time through, need to assign label to the message |
4894 | */ | 4876 | */ |
4895 | if (msec->sid == SECINITSID_UNLABELED) { | 4877 | if (msec->sid == SECINITSID_UNLABELED) { |
4896 | /* | 4878 | /* |
4897 | * Compute new sid based on current process and | 4879 | * Compute new sid based on current process and |
4898 | * message queue this message will be stored in | 4880 | * message queue this message will be stored in |
4899 | */ | 4881 | */ |
4900 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, | 4882 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, |
4901 | NULL, &msec->sid); | 4883 | NULL, &msec->sid); |
4902 | if (rc) | 4884 | if (rc) |
4903 | return rc; | 4885 | return rc; |
4904 | } | 4886 | } |
4905 | 4887 | ||
4906 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4888 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4907 | ad.u.ipc_id = msq->q_perm.key; | 4889 | ad.u.ipc_id = msq->q_perm.key; |
4908 | 4890 | ||
4909 | /* Can this process write to the queue? */ | 4891 | /* Can this process write to the queue? */ |
4910 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4892 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
4911 | MSGQ__WRITE, &ad); | 4893 | MSGQ__WRITE, &ad); |
4912 | if (!rc) | 4894 | if (!rc) |
4913 | /* Can this process send the message */ | 4895 | /* Can this process send the message */ |
4914 | rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG, | 4896 | rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG, |
4915 | MSG__SEND, &ad); | 4897 | MSG__SEND, &ad); |
4916 | if (!rc) | 4898 | if (!rc) |
4917 | /* Can the message be put in the queue? */ | 4899 | /* Can the message be put in the queue? */ |
4918 | rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ, | 4900 | rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ, |
4919 | MSGQ__ENQUEUE, &ad); | 4901 | MSGQ__ENQUEUE, &ad); |
4920 | 4902 | ||
4921 | return rc; | 4903 | return rc; |
4922 | } | 4904 | } |
4923 | 4905 | ||
4924 | static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | 4906 | static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, |
4925 | struct task_struct *target, | 4907 | struct task_struct *target, |
4926 | long type, int mode) | 4908 | long type, int mode) |
4927 | { | 4909 | { |
4928 | struct ipc_security_struct *isec; | 4910 | struct ipc_security_struct *isec; |
4929 | struct msg_security_struct *msec; | 4911 | struct msg_security_struct *msec; |
4930 | struct common_audit_data ad; | 4912 | struct common_audit_data ad; |
4931 | u32 sid = task_sid(target); | 4913 | u32 sid = task_sid(target); |
4932 | int rc; | 4914 | int rc; |
4933 | 4915 | ||
4934 | isec = msq->q_perm.security; | 4916 | isec = msq->q_perm.security; |
4935 | msec = msg->security; | 4917 | msec = msg->security; |
4936 | 4918 | ||
4937 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4919 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4938 | ad.u.ipc_id = msq->q_perm.key; | 4920 | ad.u.ipc_id = msq->q_perm.key; |
4939 | 4921 | ||
4940 | rc = avc_has_perm(sid, isec->sid, | 4922 | rc = avc_has_perm(sid, isec->sid, |
4941 | SECCLASS_MSGQ, MSGQ__READ, &ad); | 4923 | SECCLASS_MSGQ, MSGQ__READ, &ad); |
4942 | if (!rc) | 4924 | if (!rc) |
4943 | rc = avc_has_perm(sid, msec->sid, | 4925 | rc = avc_has_perm(sid, msec->sid, |
4944 | SECCLASS_MSG, MSG__RECEIVE, &ad); | 4926 | SECCLASS_MSG, MSG__RECEIVE, &ad); |
4945 | return rc; | 4927 | return rc; |
4946 | } | 4928 | } |
4947 | 4929 | ||
4948 | /* Shared Memory security operations */ | 4930 | /* Shared Memory security operations */ |
4949 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4931 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4950 | { | 4932 | { |
4951 | struct ipc_security_struct *isec; | 4933 | struct ipc_security_struct *isec; |
4952 | struct common_audit_data ad; | 4934 | struct common_audit_data ad; |
4953 | u32 sid = current_sid(); | 4935 | u32 sid = current_sid(); |
4954 | int rc; | 4936 | int rc; |
4955 | 4937 | ||
4956 | rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); | 4938 | rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); |
4957 | if (rc) | 4939 | if (rc) |
4958 | return rc; | 4940 | return rc; |
4959 | 4941 | ||
4960 | isec = shp->shm_perm.security; | 4942 | isec = shp->shm_perm.security; |
4961 | 4943 | ||
4962 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4944 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4963 | ad.u.ipc_id = shp->shm_perm.key; | 4945 | ad.u.ipc_id = shp->shm_perm.key; |
4964 | 4946 | ||
4965 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4947 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
4966 | SHM__CREATE, &ad); | 4948 | SHM__CREATE, &ad); |
4967 | if (rc) { | 4949 | if (rc) { |
4968 | ipc_free_security(&shp->shm_perm); | 4950 | ipc_free_security(&shp->shm_perm); |
4969 | return rc; | 4951 | return rc; |
4970 | } | 4952 | } |
4971 | return 0; | 4953 | return 0; |
4972 | } | 4954 | } |
4973 | 4955 | ||
4974 | static void selinux_shm_free_security(struct shmid_kernel *shp) | 4956 | static void selinux_shm_free_security(struct shmid_kernel *shp) |
4975 | { | 4957 | { |
4976 | ipc_free_security(&shp->shm_perm); | 4958 | ipc_free_security(&shp->shm_perm); |
4977 | } | 4959 | } |
4978 | 4960 | ||
4979 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4961 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4980 | { | 4962 | { |
4981 | struct ipc_security_struct *isec; | 4963 | struct ipc_security_struct *isec; |
4982 | struct common_audit_data ad; | 4964 | struct common_audit_data ad; |
4983 | u32 sid = current_sid(); | 4965 | u32 sid = current_sid(); |
4984 | 4966 | ||
4985 | isec = shp->shm_perm.security; | 4967 | isec = shp->shm_perm.security; |
4986 | 4968 | ||
4987 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4969 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4988 | ad.u.ipc_id = shp->shm_perm.key; | 4970 | ad.u.ipc_id = shp->shm_perm.key; |
4989 | 4971 | ||
4990 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4972 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
4991 | SHM__ASSOCIATE, &ad); | 4973 | SHM__ASSOCIATE, &ad); |
4992 | } | 4974 | } |
4993 | 4975 | ||
4994 | /* Note, at this point, shp is locked down */ | 4976 | /* Note, at this point, shp is locked down */ |
4995 | static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) | 4977 | static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) |
4996 | { | 4978 | { |
4997 | int perms; | 4979 | int perms; |
4998 | int err; | 4980 | int err; |
4999 | 4981 | ||
5000 | switch (cmd) { | 4982 | switch (cmd) { |
5001 | case IPC_INFO: | 4983 | case IPC_INFO: |
5002 | case SHM_INFO: | 4984 | case SHM_INFO: |
5003 | /* No specific object, just general system-wide information. */ | 4985 | /* No specific object, just general system-wide information. */ |
5004 | return task_has_system(current, SYSTEM__IPC_INFO); | 4986 | return task_has_system(current, SYSTEM__IPC_INFO); |
5005 | case IPC_STAT: | 4987 | case IPC_STAT: |
5006 | case SHM_STAT: | 4988 | case SHM_STAT: |
5007 | perms = SHM__GETATTR | SHM__ASSOCIATE; | 4989 | perms = SHM__GETATTR | SHM__ASSOCIATE; |
5008 | break; | 4990 | break; |
5009 | case IPC_SET: | 4991 | case IPC_SET: |
5010 | perms = SHM__SETATTR; | 4992 | perms = SHM__SETATTR; |
5011 | break; | 4993 | break; |
5012 | case SHM_LOCK: | 4994 | case SHM_LOCK: |
5013 | case SHM_UNLOCK: | 4995 | case SHM_UNLOCK: |
5014 | perms = SHM__LOCK; | 4996 | perms = SHM__LOCK; |
5015 | break; | 4997 | break; |
5016 | case IPC_RMID: | 4998 | case IPC_RMID: |
5017 | perms = SHM__DESTROY; | 4999 | perms = SHM__DESTROY; |
5018 | break; | 5000 | break; |
5019 | default: | 5001 | default: |
5020 | return 0; | 5002 | return 0; |
5021 | } | 5003 | } |
5022 | 5004 | ||
5023 | err = ipc_has_perm(&shp->shm_perm, perms); | 5005 | err = ipc_has_perm(&shp->shm_perm, perms); |
5024 | return err; | 5006 | return err; |
5025 | } | 5007 | } |
5026 | 5008 | ||
5027 | static int selinux_shm_shmat(struct shmid_kernel *shp, | 5009 | static int selinux_shm_shmat(struct shmid_kernel *shp, |
5028 | char __user *shmaddr, int shmflg) | 5010 | char __user *shmaddr, int shmflg) |
5029 | { | 5011 | { |
5030 | u32 perms; | 5012 | u32 perms; |
5031 | 5013 | ||
5032 | if (shmflg & SHM_RDONLY) | 5014 | if (shmflg & SHM_RDONLY) |
5033 | perms = SHM__READ; | 5015 | perms = SHM__READ; |
5034 | else | 5016 | else |
5035 | perms = SHM__READ | SHM__WRITE; | 5017 | perms = SHM__READ | SHM__WRITE; |
5036 | 5018 | ||
5037 | return ipc_has_perm(&shp->shm_perm, perms); | 5019 | return ipc_has_perm(&shp->shm_perm, perms); |
5038 | } | 5020 | } |
5039 | 5021 | ||
5040 | /* Semaphore security operations */ | 5022 | /* Semaphore security operations */ |
5041 | static int selinux_sem_alloc_security(struct sem_array *sma) | 5023 | static int selinux_sem_alloc_security(struct sem_array *sma) |
5042 | { | 5024 | { |
5043 | struct ipc_security_struct *isec; | 5025 | struct ipc_security_struct *isec; |
5044 | struct common_audit_data ad; | 5026 | struct common_audit_data ad; |
5045 | u32 sid = current_sid(); | 5027 | u32 sid = current_sid(); |
5046 | int rc; | 5028 | int rc; |
5047 | 5029 | ||
5048 | rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); | 5030 | rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); |
5049 | if (rc) | 5031 | if (rc) |
5050 | return rc; | 5032 | return rc; |
5051 | 5033 | ||
5052 | isec = sma->sem_perm.security; | 5034 | isec = sma->sem_perm.security; |
5053 | 5035 | ||
5054 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5036 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
5055 | ad.u.ipc_id = sma->sem_perm.key; | 5037 | ad.u.ipc_id = sma->sem_perm.key; |
5056 | 5038 | ||
5057 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5039 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
5058 | SEM__CREATE, &ad); | 5040 | SEM__CREATE, &ad); |
5059 | if (rc) { | 5041 | if (rc) { |
5060 | ipc_free_security(&sma->sem_perm); | 5042 | ipc_free_security(&sma->sem_perm); |
5061 | return rc; | 5043 | return rc; |
5062 | } | 5044 | } |
5063 | return 0; | 5045 | return 0; |
5064 | } | 5046 | } |
5065 | 5047 | ||
5066 | static void selinux_sem_free_security(struct sem_array *sma) | 5048 | static void selinux_sem_free_security(struct sem_array *sma) |
5067 | { | 5049 | { |
5068 | ipc_free_security(&sma->sem_perm); | 5050 | ipc_free_security(&sma->sem_perm); |
5069 | } | 5051 | } |
5070 | 5052 | ||
5071 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5053 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
5072 | { | 5054 | { |
5073 | struct ipc_security_struct *isec; | 5055 | struct ipc_security_struct *isec; |
5074 | struct common_audit_data ad; | 5056 | struct common_audit_data ad; |
5075 | u32 sid = current_sid(); | 5057 | u32 sid = current_sid(); |
5076 | 5058 | ||
5077 | isec = sma->sem_perm.security; | 5059 | isec = sma->sem_perm.security; |
5078 | 5060 | ||
5079 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5061 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
5080 | ad.u.ipc_id = sma->sem_perm.key; | 5062 | ad.u.ipc_id = sma->sem_perm.key; |
5081 | 5063 | ||
5082 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5064 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
5083 | SEM__ASSOCIATE, &ad); | 5065 | SEM__ASSOCIATE, &ad); |
5084 | } | 5066 | } |
5085 | 5067 | ||
5086 | /* Note, at this point, sma is locked down */ | 5068 | /* Note, at this point, sma is locked down */ |
5087 | static int selinux_sem_semctl(struct sem_array *sma, int cmd) | 5069 | static int selinux_sem_semctl(struct sem_array *sma, int cmd) |
5088 | { | 5070 | { |
5089 | int err; | 5071 | int err; |
5090 | u32 perms; | 5072 | u32 perms; |
5091 | 5073 | ||
5092 | switch (cmd) { | 5074 | switch (cmd) { |
5093 | case IPC_INFO: | 5075 | case IPC_INFO: |
5094 | case SEM_INFO: | 5076 | case SEM_INFO: |
5095 | /* No specific object, just general system-wide information. */ | 5077 | /* No specific object, just general system-wide information. */ |
5096 | return task_has_system(current, SYSTEM__IPC_INFO); | 5078 | return task_has_system(current, SYSTEM__IPC_INFO); |
5097 | case GETPID: | 5079 | case GETPID: |
5098 | case GETNCNT: | 5080 | case GETNCNT: |
5099 | case GETZCNT: | 5081 | case GETZCNT: |
5100 | perms = SEM__GETATTR; | 5082 | perms = SEM__GETATTR; |
5101 | break; | 5083 | break; |
5102 | case GETVAL: | 5084 | case GETVAL: |
5103 | case GETALL: | 5085 | case GETALL: |
5104 | perms = SEM__READ; | 5086 | perms = SEM__READ; |
5105 | break; | 5087 | break; |
5106 | case SETVAL: | 5088 | case SETVAL: |
5107 | case SETALL: | 5089 | case SETALL: |
5108 | perms = SEM__WRITE; | 5090 | perms = SEM__WRITE; |
5109 | break; | 5091 | break; |
5110 | case IPC_RMID: | 5092 | case IPC_RMID: |
5111 | perms = SEM__DESTROY; | 5093 | perms = SEM__DESTROY; |
5112 | break; | 5094 | break; |
5113 | case IPC_SET: | 5095 | case IPC_SET: |
5114 | perms = SEM__SETATTR; | 5096 | perms = SEM__SETATTR; |
5115 | break; | 5097 | break; |
5116 | case IPC_STAT: | 5098 | case IPC_STAT: |
5117 | case SEM_STAT: | 5099 | case SEM_STAT: |
5118 | perms = SEM__GETATTR | SEM__ASSOCIATE; | 5100 | perms = SEM__GETATTR | SEM__ASSOCIATE; |
5119 | break; | 5101 | break; |
5120 | default: | 5102 | default: |
5121 | return 0; | 5103 | return 0; |
5122 | } | 5104 | } |
5123 | 5105 | ||
5124 | err = ipc_has_perm(&sma->sem_perm, perms); | 5106 | err = ipc_has_perm(&sma->sem_perm, perms); |
5125 | return err; | 5107 | return err; |
5126 | } | 5108 | } |
5127 | 5109 | ||
5128 | static int selinux_sem_semop(struct sem_array *sma, | 5110 | static int selinux_sem_semop(struct sem_array *sma, |
5129 | struct sembuf *sops, unsigned nsops, int alter) | 5111 | struct sembuf *sops, unsigned nsops, int alter) |
5130 | { | 5112 | { |
5131 | u32 perms; | 5113 | u32 perms; |
5132 | 5114 | ||
5133 | if (alter) | 5115 | if (alter) |
5134 | perms = SEM__READ | SEM__WRITE; | 5116 | perms = SEM__READ | SEM__WRITE; |
5135 | else | 5117 | else |
5136 | perms = SEM__READ; | 5118 | perms = SEM__READ; |
5137 | 5119 | ||
5138 | return ipc_has_perm(&sma->sem_perm, perms); | 5120 | return ipc_has_perm(&sma->sem_perm, perms); |
5139 | } | 5121 | } |
5140 | 5122 | ||
5141 | static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | 5123 | static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) |
5142 | { | 5124 | { |
5143 | u32 av = 0; | 5125 | u32 av = 0; |
5144 | 5126 | ||
5145 | av = 0; | 5127 | av = 0; |
5146 | if (flag & S_IRUGO) | 5128 | if (flag & S_IRUGO) |
5147 | av |= IPC__UNIX_READ; | 5129 | av |= IPC__UNIX_READ; |
5148 | if (flag & S_IWUGO) | 5130 | if (flag & S_IWUGO) |
5149 | av |= IPC__UNIX_WRITE; | 5131 | av |= IPC__UNIX_WRITE; |
5150 | 5132 | ||
5151 | if (av == 0) | 5133 | if (av == 0) |
5152 | return 0; | 5134 | return 0; |
5153 | 5135 | ||
5154 | return ipc_has_perm(ipcp, av); | 5136 | return ipc_has_perm(ipcp, av); |
5155 | } | 5137 | } |
5156 | 5138 | ||
5157 | static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | 5139 | static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) |
5158 | { | 5140 | { |
5159 | struct ipc_security_struct *isec = ipcp->security; | 5141 | struct ipc_security_struct *isec = ipcp->security; |
5160 | *secid = isec->sid; | 5142 | *secid = isec->sid; |
5161 | } | 5143 | } |
5162 | 5144 | ||
5163 | static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) | 5145 | static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) |
5164 | { | 5146 | { |
5165 | if (inode) | 5147 | if (inode) |
5166 | inode_doinit_with_dentry(inode, dentry); | 5148 | inode_doinit_with_dentry(inode, dentry); |
5167 | } | 5149 | } |
5168 | 5150 | ||
5169 | static int selinux_getprocattr(struct task_struct *p, | 5151 | static int selinux_getprocattr(struct task_struct *p, |
5170 | char *name, char **value) | 5152 | char *name, char **value) |
5171 | { | 5153 | { |
5172 | const struct task_security_struct *__tsec; | 5154 | const struct task_security_struct *__tsec; |
5173 | u32 sid; | 5155 | u32 sid; |
5174 | int error; | 5156 | int error; |
5175 | unsigned len; | 5157 | unsigned len; |
5176 | 5158 | ||
5177 | if (current != p) { | 5159 | if (current != p) { |
5178 | error = current_has_perm(p, PROCESS__GETATTR); | 5160 | error = current_has_perm(p, PROCESS__GETATTR); |
5179 | if (error) | 5161 | if (error) |
5180 | return error; | 5162 | return error; |
5181 | } | 5163 | } |
5182 | 5164 | ||
5183 | rcu_read_lock(); | 5165 | rcu_read_lock(); |
5184 | __tsec = __task_cred(p)->security; | 5166 | __tsec = __task_cred(p)->security; |
5185 | 5167 | ||
5186 | if (!strcmp(name, "current")) | 5168 | if (!strcmp(name, "current")) |
5187 | sid = __tsec->sid; | 5169 | sid = __tsec->sid; |
5188 | else if (!strcmp(name, "prev")) | 5170 | else if (!strcmp(name, "prev")) |
5189 | sid = __tsec->osid; | 5171 | sid = __tsec->osid; |
5190 | else if (!strcmp(name, "exec")) | 5172 | else if (!strcmp(name, "exec")) |
5191 | sid = __tsec->exec_sid; | 5173 | sid = __tsec->exec_sid; |
5192 | else if (!strcmp(name, "fscreate")) | 5174 | else if (!strcmp(name, "fscreate")) |
5193 | sid = __tsec->create_sid; | 5175 | sid = __tsec->create_sid; |
5194 | else if (!strcmp(name, "keycreate")) | 5176 | else if (!strcmp(name, "keycreate")) |
5195 | sid = __tsec->keycreate_sid; | 5177 | sid = __tsec->keycreate_sid; |
5196 | else if (!strcmp(name, "sockcreate")) | 5178 | else if (!strcmp(name, "sockcreate")) |
5197 | sid = __tsec->sockcreate_sid; | 5179 | sid = __tsec->sockcreate_sid; |
5198 | else | 5180 | else |
5199 | goto invalid; | 5181 | goto invalid; |
5200 | rcu_read_unlock(); | 5182 | rcu_read_unlock(); |
5201 | 5183 | ||
5202 | if (!sid) | 5184 | if (!sid) |
5203 | return 0; | 5185 | return 0; |
5204 | 5186 | ||
5205 | error = security_sid_to_context(sid, value, &len); | 5187 | error = security_sid_to_context(sid, value, &len); |
5206 | if (error) | 5188 | if (error) |
5207 | return error; | 5189 | return error; |
5208 | return len; | 5190 | return len; |
5209 | 5191 | ||
5210 | invalid: | 5192 | invalid: |
5211 | rcu_read_unlock(); | 5193 | rcu_read_unlock(); |
5212 | return -EINVAL; | 5194 | return -EINVAL; |
5213 | } | 5195 | } |
5214 | 5196 | ||
5215 | static int selinux_setprocattr(struct task_struct *p, | 5197 | static int selinux_setprocattr(struct task_struct *p, |
5216 | char *name, void *value, size_t size) | 5198 | char *name, void *value, size_t size) |
5217 | { | 5199 | { |
5218 | struct task_security_struct *tsec; | 5200 | struct task_security_struct *tsec; |
5219 | struct task_struct *tracer; | 5201 | struct task_struct *tracer; |
5220 | struct cred *new; | 5202 | struct cred *new; |
5221 | u32 sid = 0, ptsid; | 5203 | u32 sid = 0, ptsid; |
5222 | int error; | 5204 | int error; |
5223 | char *str = value; | 5205 | char *str = value; |
5224 | 5206 | ||
5225 | if (current != p) { | 5207 | if (current != p) { |
5226 | /* SELinux only allows a process to change its own | 5208 | /* SELinux only allows a process to change its own |
5227 | security attributes. */ | 5209 | security attributes. */ |
5228 | return -EACCES; | 5210 | return -EACCES; |
5229 | } | 5211 | } |
5230 | 5212 | ||
5231 | /* | 5213 | /* |
5232 | * Basic control over ability to set these attributes at all. | 5214 | * Basic control over ability to set these attributes at all. |
5233 | * current == p, but we'll pass them separately in case the | 5215 | * current == p, but we'll pass them separately in case the |
5234 | * above restriction is ever removed. | 5216 | * above restriction is ever removed. |
5235 | */ | 5217 | */ |
5236 | if (!strcmp(name, "exec")) | 5218 | if (!strcmp(name, "exec")) |
5237 | error = current_has_perm(p, PROCESS__SETEXEC); | 5219 | error = current_has_perm(p, PROCESS__SETEXEC); |
5238 | else if (!strcmp(name, "fscreate")) | 5220 | else if (!strcmp(name, "fscreate")) |
5239 | error = current_has_perm(p, PROCESS__SETFSCREATE); | 5221 | error = current_has_perm(p, PROCESS__SETFSCREATE); |
5240 | else if (!strcmp(name, "keycreate")) | 5222 | else if (!strcmp(name, "keycreate")) |
5241 | error = current_has_perm(p, PROCESS__SETKEYCREATE); | 5223 | error = current_has_perm(p, PROCESS__SETKEYCREATE); |
5242 | else if (!strcmp(name, "sockcreate")) | 5224 | else if (!strcmp(name, "sockcreate")) |
5243 | error = current_has_perm(p, PROCESS__SETSOCKCREATE); | 5225 | error = current_has_perm(p, PROCESS__SETSOCKCREATE); |
5244 | else if (!strcmp(name, "current")) | 5226 | else if (!strcmp(name, "current")) |
5245 | error = current_has_perm(p, PROCESS__SETCURRENT); | 5227 | error = current_has_perm(p, PROCESS__SETCURRENT); |
5246 | else | 5228 | else |
5247 | error = -EINVAL; | 5229 | error = -EINVAL; |
5248 | if (error) | 5230 | if (error) |
5249 | return error; | 5231 | return error; |
5250 | 5232 | ||
5251 | /* Obtain a SID for the context, if one was specified. */ | 5233 | /* Obtain a SID for the context, if one was specified. */ |
5252 | if (size && str[1] && str[1] != '\n') { | 5234 | if (size && str[1] && str[1] != '\n') { |
5253 | if (str[size-1] == '\n') { | 5235 | if (str[size-1] == '\n') { |
5254 | str[size-1] = 0; | 5236 | str[size-1] = 0; |
5255 | size--; | 5237 | size--; |
5256 | } | 5238 | } |
5257 | error = security_context_to_sid(value, size, &sid); | 5239 | error = security_context_to_sid(value, size, &sid); |
5258 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 5240 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5259 | if (!capable(CAP_MAC_ADMIN)) | 5241 | if (!capable(CAP_MAC_ADMIN)) |
5260 | return error; | 5242 | return error; |
5261 | error = security_context_to_sid_force(value, size, | 5243 | error = security_context_to_sid_force(value, size, |
5262 | &sid); | 5244 | &sid); |
5263 | } | 5245 | } |
5264 | if (error) | 5246 | if (error) |
5265 | return error; | 5247 | return error; |
5266 | } | 5248 | } |
5267 | 5249 | ||
5268 | new = prepare_creds(); | 5250 | new = prepare_creds(); |
5269 | if (!new) | 5251 | if (!new) |
5270 | return -ENOMEM; | 5252 | return -ENOMEM; |
5271 | 5253 | ||
5272 | /* Permission checking based on the specified context is | 5254 | /* Permission checking based on the specified context is |
5273 | performed during the actual operation (execve, | 5255 | performed during the actual operation (execve, |
5274 | open/mkdir/...), when we know the full context of the | 5256 | open/mkdir/...), when we know the full context of the |
5275 | operation. See selinux_bprm_set_creds for the execve | 5257 | operation. See selinux_bprm_set_creds for the execve |
5276 | checks and may_create for the file creation checks. The | 5258 | checks and may_create for the file creation checks. The |
5277 | operation will then fail if the context is not permitted. */ | 5259 | operation will then fail if the context is not permitted. */ |
5278 | tsec = new->security; | 5260 | tsec = new->security; |
5279 | if (!strcmp(name, "exec")) { | 5261 | if (!strcmp(name, "exec")) { |
5280 | tsec->exec_sid = sid; | 5262 | tsec->exec_sid = sid; |
5281 | } else if (!strcmp(name, "fscreate")) { | 5263 | } else if (!strcmp(name, "fscreate")) { |
5282 | tsec->create_sid = sid; | 5264 | tsec->create_sid = sid; |
5283 | } else if (!strcmp(name, "keycreate")) { | 5265 | } else if (!strcmp(name, "keycreate")) { |
5284 | error = may_create_key(sid, p); | 5266 | error = may_create_key(sid, p); |
5285 | if (error) | 5267 | if (error) |
5286 | goto abort_change; | 5268 | goto abort_change; |
5287 | tsec->keycreate_sid = sid; | 5269 | tsec->keycreate_sid = sid; |
5288 | } else if (!strcmp(name, "sockcreate")) { | 5270 | } else if (!strcmp(name, "sockcreate")) { |
5289 | tsec->sockcreate_sid = sid; | 5271 | tsec->sockcreate_sid = sid; |
5290 | } else if (!strcmp(name, "current")) { | 5272 | } else if (!strcmp(name, "current")) { |
5291 | error = -EINVAL; | 5273 | error = -EINVAL; |
5292 | if (sid == 0) | 5274 | if (sid == 0) |
5293 | goto abort_change; | 5275 | goto abort_change; |
5294 | 5276 | ||
5295 | /* Only allow single threaded processes to change context */ | 5277 | /* Only allow single threaded processes to change context */ |
5296 | error = -EPERM; | 5278 | error = -EPERM; |
5297 | if (!current_is_single_threaded()) { | 5279 | if (!current_is_single_threaded()) { |
5298 | error = security_bounded_transition(tsec->sid, sid); | 5280 | error = security_bounded_transition(tsec->sid, sid); |
5299 | if (error) | 5281 | if (error) |
5300 | goto abort_change; | 5282 | goto abort_change; |
5301 | } | 5283 | } |
5302 | 5284 | ||
5303 | /* Check permissions for the transition. */ | 5285 | /* Check permissions for the transition. */ |
5304 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5286 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |
5305 | PROCESS__DYNTRANSITION, NULL); | 5287 | PROCESS__DYNTRANSITION, NULL); |
5306 | if (error) | 5288 | if (error) |
5307 | goto abort_change; | 5289 | goto abort_change; |
5308 | 5290 | ||
5309 | /* Check for ptracing, and update the task SID if ok. | 5291 | /* Check for ptracing, and update the task SID if ok. |
5310 | Otherwise, leave SID unchanged and fail. */ | 5292 | Otherwise, leave SID unchanged and fail. */ |
5311 | ptsid = 0; | 5293 | ptsid = 0; |
5312 | task_lock(p); | 5294 | task_lock(p); |
5313 | tracer = ptrace_parent(p); | 5295 | tracer = ptrace_parent(p); |
5314 | if (tracer) | 5296 | if (tracer) |
5315 | ptsid = task_sid(tracer); | 5297 | ptsid = task_sid(tracer); |
5316 | task_unlock(p); | 5298 | task_unlock(p); |
5317 | 5299 | ||
5318 | if (tracer) { | 5300 | if (tracer) { |
5319 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 5301 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
5320 | PROCESS__PTRACE, NULL); | 5302 | PROCESS__PTRACE, NULL); |
5321 | if (error) | 5303 | if (error) |
5322 | goto abort_change; | 5304 | goto abort_change; |
5323 | } | 5305 | } |
5324 | 5306 | ||
5325 | tsec->sid = sid; | 5307 | tsec->sid = sid; |
5326 | } else { | 5308 | } else { |
5327 | error = -EINVAL; | 5309 | error = -EINVAL; |
5328 | goto abort_change; | 5310 | goto abort_change; |
5329 | } | 5311 | } |
5330 | 5312 | ||
5331 | commit_creds(new); | 5313 | commit_creds(new); |
5332 | return size; | 5314 | return size; |
5333 | 5315 | ||
5334 | abort_change: | 5316 | abort_change: |
5335 | abort_creds(new); | 5317 | abort_creds(new); |
5336 | return error; | 5318 | return error; |
5337 | } | 5319 | } |
5338 | 5320 | ||
5339 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5321 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
5340 | { | 5322 | { |
5341 | return security_sid_to_context(secid, secdata, seclen); | 5323 | return security_sid_to_context(secid, secdata, seclen); |
5342 | } | 5324 | } |
5343 | 5325 | ||
5344 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 5326 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
5345 | { | 5327 | { |
5346 | return security_context_to_sid(secdata, seclen, secid); | 5328 | return security_context_to_sid(secdata, seclen, secid); |
5347 | } | 5329 | } |
5348 | 5330 | ||
5349 | static void selinux_release_secctx(char *secdata, u32 seclen) | 5331 | static void selinux_release_secctx(char *secdata, u32 seclen) |
5350 | { | 5332 | { |
5351 | kfree(secdata); | 5333 | kfree(secdata); |
5352 | } | 5334 | } |
5353 | 5335 | ||
5354 | /* | 5336 | /* |
5355 | * called with inode->i_mutex locked | 5337 | * called with inode->i_mutex locked |
5356 | */ | 5338 | */ |
5357 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | 5339 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) |
5358 | { | 5340 | { |
5359 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | 5341 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); |
5360 | } | 5342 | } |
5361 | 5343 | ||
5362 | /* | 5344 | /* |
5363 | * called with inode->i_mutex locked | 5345 | * called with inode->i_mutex locked |
5364 | */ | 5346 | */ |
5365 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | 5347 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) |
5366 | { | 5348 | { |
5367 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | 5349 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); |
5368 | } | 5350 | } |
5369 | 5351 | ||
5370 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | 5352 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) |
5371 | { | 5353 | { |
5372 | int len = 0; | 5354 | int len = 0; |
5373 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | 5355 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, |
5374 | ctx, true); | 5356 | ctx, true); |
5375 | if (len < 0) | 5357 | if (len < 0) |
5376 | return len; | 5358 | return len; |
5377 | *ctxlen = len; | 5359 | *ctxlen = len; |
5378 | return 0; | 5360 | return 0; |
5379 | } | 5361 | } |
5380 | #ifdef CONFIG_KEYS | 5362 | #ifdef CONFIG_KEYS |
5381 | 5363 | ||
5382 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5364 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
5383 | unsigned long flags) | 5365 | unsigned long flags) |
5384 | { | 5366 | { |
5385 | const struct task_security_struct *tsec; | 5367 | const struct task_security_struct *tsec; |
5386 | struct key_security_struct *ksec; | 5368 | struct key_security_struct *ksec; |
5387 | 5369 | ||
5388 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); | 5370 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); |
5389 | if (!ksec) | 5371 | if (!ksec) |
5390 | return -ENOMEM; | 5372 | return -ENOMEM; |
5391 | 5373 | ||
5392 | tsec = cred->security; | 5374 | tsec = cred->security; |
5393 | if (tsec->keycreate_sid) | 5375 | if (tsec->keycreate_sid) |
5394 | ksec->sid = tsec->keycreate_sid; | 5376 | ksec->sid = tsec->keycreate_sid; |
5395 | else | 5377 | else |
5396 | ksec->sid = tsec->sid; | 5378 | ksec->sid = tsec->sid; |
5397 | 5379 | ||
5398 | k->security = ksec; | 5380 | k->security = ksec; |
5399 | return 0; | 5381 | return 0; |
5400 | } | 5382 | } |
5401 | 5383 | ||
5402 | static void selinux_key_free(struct key *k) | 5384 | static void selinux_key_free(struct key *k) |
5403 | { | 5385 | { |
5404 | struct key_security_struct *ksec = k->security; | 5386 | struct key_security_struct *ksec = k->security; |
5405 | 5387 | ||
5406 | k->security = NULL; | 5388 | k->security = NULL; |
5407 | kfree(ksec); | 5389 | kfree(ksec); |
5408 | } | 5390 | } |
5409 | 5391 | ||
5410 | static int selinux_key_permission(key_ref_t key_ref, | 5392 | static int selinux_key_permission(key_ref_t key_ref, |
5411 | const struct cred *cred, | 5393 | const struct cred *cred, |
5412 | key_perm_t perm) | 5394 | key_perm_t perm) |
5413 | { | 5395 | { |
5414 | struct key *key; | 5396 | struct key *key; |
5415 | struct key_security_struct *ksec; | 5397 | struct key_security_struct *ksec; |
5416 | u32 sid; | 5398 | u32 sid; |
5417 | 5399 | ||
5418 | /* if no specific permissions are requested, we skip the | 5400 | /* if no specific permissions are requested, we skip the |
5419 | permission check. No serious, additional covert channels | 5401 | permission check. No serious, additional covert channels |
5420 | appear to be created. */ | 5402 | appear to be created. */ |
5421 | if (perm == 0) | 5403 | if (perm == 0) |
5422 | return 0; | 5404 | return 0; |
5423 | 5405 | ||
5424 | sid = cred_sid(cred); | 5406 | sid = cred_sid(cred); |
5425 | 5407 | ||
5426 | key = key_ref_to_ptr(key_ref); | 5408 | key = key_ref_to_ptr(key_ref); |
5427 | ksec = key->security; | 5409 | ksec = key->security; |
5428 | 5410 | ||
5429 | return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); | 5411 | return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); |
5430 | } | 5412 | } |
5431 | 5413 | ||
5432 | static int selinux_key_getsecurity(struct key *key, char **_buffer) | 5414 | static int selinux_key_getsecurity(struct key *key, char **_buffer) |
5433 | { | 5415 | { |
5434 | struct key_security_struct *ksec = key->security; | 5416 | struct key_security_struct *ksec = key->security; |
5435 | char *context = NULL; | 5417 | char *context = NULL; |
5436 | unsigned len; | 5418 | unsigned len; |
5437 | int rc; | 5419 | int rc; |
5438 | 5420 | ||
5439 | rc = security_sid_to_context(ksec->sid, &context, &len); | 5421 | rc = security_sid_to_context(ksec->sid, &context, &len); |
5440 | if (!rc) | 5422 | if (!rc) |
5441 | rc = len; | 5423 | rc = len; |
5442 | *_buffer = context; | 5424 | *_buffer = context; |
5443 | return rc; | 5425 | return rc; |
5444 | } | 5426 | } |
5445 | 5427 | ||
5446 | #endif | 5428 | #endif |
5447 | 5429 | ||
5448 | static struct security_operations selinux_ops = { | 5430 | static struct security_operations selinux_ops = { |
5449 | .name = "selinux", | 5431 | .name = "selinux", |
5450 | 5432 | ||
5451 | .ptrace_access_check = selinux_ptrace_access_check, | 5433 | .ptrace_access_check = selinux_ptrace_access_check, |
5452 | .ptrace_traceme = selinux_ptrace_traceme, | 5434 | .ptrace_traceme = selinux_ptrace_traceme, |
5453 | .capget = selinux_capget, | 5435 | .capget = selinux_capget, |
5454 | .capset = selinux_capset, | 5436 | .capset = selinux_capset, |
5455 | .capable = selinux_capable, | 5437 | .capable = selinux_capable, |
5456 | .quotactl = selinux_quotactl, | 5438 | .quotactl = selinux_quotactl, |
5457 | .quota_on = selinux_quota_on, | 5439 | .quota_on = selinux_quota_on, |
5458 | .syslog = selinux_syslog, | 5440 | .syslog = selinux_syslog, |
5459 | .vm_enough_memory = selinux_vm_enough_memory, | 5441 | .vm_enough_memory = selinux_vm_enough_memory, |
5460 | 5442 | ||
5461 | .netlink_send = selinux_netlink_send, | 5443 | .netlink_send = selinux_netlink_send, |
5462 | .netlink_recv = selinux_netlink_recv, | ||
5463 | 5444 | ||
5464 | .bprm_set_creds = selinux_bprm_set_creds, | 5445 | .bprm_set_creds = selinux_bprm_set_creds, |
5465 | .bprm_committing_creds = selinux_bprm_committing_creds, | 5446 | .bprm_committing_creds = selinux_bprm_committing_creds, |
5466 | .bprm_committed_creds = selinux_bprm_committed_creds, | 5447 | .bprm_committed_creds = selinux_bprm_committed_creds, |
5467 | .bprm_secureexec = selinux_bprm_secureexec, | 5448 | .bprm_secureexec = selinux_bprm_secureexec, |
5468 | 5449 | ||
5469 | .sb_alloc_security = selinux_sb_alloc_security, | 5450 | .sb_alloc_security = selinux_sb_alloc_security, |
5470 | .sb_free_security = selinux_sb_free_security, | 5451 | .sb_free_security = selinux_sb_free_security, |
5471 | .sb_copy_data = selinux_sb_copy_data, | 5452 | .sb_copy_data = selinux_sb_copy_data, |
5472 | .sb_remount = selinux_sb_remount, | 5453 | .sb_remount = selinux_sb_remount, |
5473 | .sb_kern_mount = selinux_sb_kern_mount, | 5454 | .sb_kern_mount = selinux_sb_kern_mount, |
5474 | .sb_show_options = selinux_sb_show_options, | 5455 | .sb_show_options = selinux_sb_show_options, |
5475 | .sb_statfs = selinux_sb_statfs, | 5456 | .sb_statfs = selinux_sb_statfs, |
5476 | .sb_mount = selinux_mount, | 5457 | .sb_mount = selinux_mount, |
5477 | .sb_umount = selinux_umount, | 5458 | .sb_umount = selinux_umount, |
5478 | .sb_set_mnt_opts = selinux_set_mnt_opts, | 5459 | .sb_set_mnt_opts = selinux_set_mnt_opts, |
5479 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | 5460 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, |
5480 | .sb_parse_opts_str = selinux_parse_opts_str, | 5461 | .sb_parse_opts_str = selinux_parse_opts_str, |
5481 | 5462 | ||
5482 | 5463 | ||
5483 | .inode_alloc_security = selinux_inode_alloc_security, | 5464 | .inode_alloc_security = selinux_inode_alloc_security, |
5484 | .inode_free_security = selinux_inode_free_security, | 5465 | .inode_free_security = selinux_inode_free_security, |
5485 | .inode_init_security = selinux_inode_init_security, | 5466 | .inode_init_security = selinux_inode_init_security, |
5486 | .inode_create = selinux_inode_create, | 5467 | .inode_create = selinux_inode_create, |
5487 | .inode_link = selinux_inode_link, | 5468 | .inode_link = selinux_inode_link, |
5488 | .inode_unlink = selinux_inode_unlink, | 5469 | .inode_unlink = selinux_inode_unlink, |
5489 | .inode_symlink = selinux_inode_symlink, | 5470 | .inode_symlink = selinux_inode_symlink, |
5490 | .inode_mkdir = selinux_inode_mkdir, | 5471 | .inode_mkdir = selinux_inode_mkdir, |
5491 | .inode_rmdir = selinux_inode_rmdir, | 5472 | .inode_rmdir = selinux_inode_rmdir, |
5492 | .inode_mknod = selinux_inode_mknod, | 5473 | .inode_mknod = selinux_inode_mknod, |
5493 | .inode_rename = selinux_inode_rename, | 5474 | .inode_rename = selinux_inode_rename, |
5494 | .inode_readlink = selinux_inode_readlink, | 5475 | .inode_readlink = selinux_inode_readlink, |
5495 | .inode_follow_link = selinux_inode_follow_link, | 5476 | .inode_follow_link = selinux_inode_follow_link, |
5496 | .inode_permission = selinux_inode_permission, | 5477 | .inode_permission = selinux_inode_permission, |
5497 | .inode_setattr = selinux_inode_setattr, | 5478 | .inode_setattr = selinux_inode_setattr, |
5498 | .inode_getattr = selinux_inode_getattr, | 5479 | .inode_getattr = selinux_inode_getattr, |
5499 | .inode_setxattr = selinux_inode_setxattr, | 5480 | .inode_setxattr = selinux_inode_setxattr, |
5500 | .inode_post_setxattr = selinux_inode_post_setxattr, | 5481 | .inode_post_setxattr = selinux_inode_post_setxattr, |
5501 | .inode_getxattr = selinux_inode_getxattr, | 5482 | .inode_getxattr = selinux_inode_getxattr, |
5502 | .inode_listxattr = selinux_inode_listxattr, | 5483 | .inode_listxattr = selinux_inode_listxattr, |
5503 | .inode_removexattr = selinux_inode_removexattr, | 5484 | .inode_removexattr = selinux_inode_removexattr, |
5504 | .inode_getsecurity = selinux_inode_getsecurity, | 5485 | .inode_getsecurity = selinux_inode_getsecurity, |
5505 | .inode_setsecurity = selinux_inode_setsecurity, | 5486 | .inode_setsecurity = selinux_inode_setsecurity, |
5506 | .inode_listsecurity = selinux_inode_listsecurity, | 5487 | .inode_listsecurity = selinux_inode_listsecurity, |
5507 | .inode_getsecid = selinux_inode_getsecid, | 5488 | .inode_getsecid = selinux_inode_getsecid, |
5508 | 5489 | ||
5509 | .file_permission = selinux_file_permission, | 5490 | .file_permission = selinux_file_permission, |
5510 | .file_alloc_security = selinux_file_alloc_security, | 5491 | .file_alloc_security = selinux_file_alloc_security, |
5511 | .file_free_security = selinux_file_free_security, | 5492 | .file_free_security = selinux_file_free_security, |
5512 | .file_ioctl = selinux_file_ioctl, | 5493 | .file_ioctl = selinux_file_ioctl, |
5513 | .file_mmap = selinux_file_mmap, | 5494 | .file_mmap = selinux_file_mmap, |
5514 | .file_mprotect = selinux_file_mprotect, | 5495 | .file_mprotect = selinux_file_mprotect, |
5515 | .file_lock = selinux_file_lock, | 5496 | .file_lock = selinux_file_lock, |
5516 | .file_fcntl = selinux_file_fcntl, | 5497 | .file_fcntl = selinux_file_fcntl, |
5517 | .file_set_fowner = selinux_file_set_fowner, | 5498 | .file_set_fowner = selinux_file_set_fowner, |
5518 | .file_send_sigiotask = selinux_file_send_sigiotask, | 5499 | .file_send_sigiotask = selinux_file_send_sigiotask, |
5519 | .file_receive = selinux_file_receive, | 5500 | .file_receive = selinux_file_receive, |
5520 | 5501 | ||
5521 | .dentry_open = selinux_dentry_open, | 5502 | .dentry_open = selinux_dentry_open, |
5522 | 5503 | ||
5523 | .task_create = selinux_task_create, | 5504 | .task_create = selinux_task_create, |
5524 | .cred_alloc_blank = selinux_cred_alloc_blank, | 5505 | .cred_alloc_blank = selinux_cred_alloc_blank, |
5525 | .cred_free = selinux_cred_free, | 5506 | .cred_free = selinux_cred_free, |
5526 | .cred_prepare = selinux_cred_prepare, | 5507 | .cred_prepare = selinux_cred_prepare, |
5527 | .cred_transfer = selinux_cred_transfer, | 5508 | .cred_transfer = selinux_cred_transfer, |
5528 | .kernel_act_as = selinux_kernel_act_as, | 5509 | .kernel_act_as = selinux_kernel_act_as, |
5529 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5510 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5530 | .kernel_module_request = selinux_kernel_module_request, | 5511 | .kernel_module_request = selinux_kernel_module_request, |
5531 | .task_setpgid = selinux_task_setpgid, | 5512 | .task_setpgid = selinux_task_setpgid, |
5532 | .task_getpgid = selinux_task_getpgid, | 5513 | .task_getpgid = selinux_task_getpgid, |
5533 | .task_getsid = selinux_task_getsid, | 5514 | .task_getsid = selinux_task_getsid, |
5534 | .task_getsecid = selinux_task_getsecid, | 5515 | .task_getsecid = selinux_task_getsecid, |
5535 | .task_setnice = selinux_task_setnice, | 5516 | .task_setnice = selinux_task_setnice, |
5536 | .task_setioprio = selinux_task_setioprio, | 5517 | .task_setioprio = selinux_task_setioprio, |
5537 | .task_getioprio = selinux_task_getioprio, | 5518 | .task_getioprio = selinux_task_getioprio, |
5538 | .task_setrlimit = selinux_task_setrlimit, | 5519 | .task_setrlimit = selinux_task_setrlimit, |
5539 | .task_setscheduler = selinux_task_setscheduler, | 5520 | .task_setscheduler = selinux_task_setscheduler, |
5540 | .task_getscheduler = selinux_task_getscheduler, | 5521 | .task_getscheduler = selinux_task_getscheduler, |
5541 | .task_movememory = selinux_task_movememory, | 5522 | .task_movememory = selinux_task_movememory, |
5542 | .task_kill = selinux_task_kill, | 5523 | .task_kill = selinux_task_kill, |
5543 | .task_wait = selinux_task_wait, | 5524 | .task_wait = selinux_task_wait, |
5544 | .task_to_inode = selinux_task_to_inode, | 5525 | .task_to_inode = selinux_task_to_inode, |
5545 | 5526 | ||
5546 | .ipc_permission = selinux_ipc_permission, | 5527 | .ipc_permission = selinux_ipc_permission, |
5547 | .ipc_getsecid = selinux_ipc_getsecid, | 5528 | .ipc_getsecid = selinux_ipc_getsecid, |
5548 | 5529 | ||
5549 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, | 5530 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, |
5550 | .msg_msg_free_security = selinux_msg_msg_free_security, | 5531 | .msg_msg_free_security = selinux_msg_msg_free_security, |
5551 | 5532 | ||
5552 | .msg_queue_alloc_security = selinux_msg_queue_alloc_security, | 5533 | .msg_queue_alloc_security = selinux_msg_queue_alloc_security, |
5553 | .msg_queue_free_security = selinux_msg_queue_free_security, | 5534 | .msg_queue_free_security = selinux_msg_queue_free_security, |
5554 | .msg_queue_associate = selinux_msg_queue_associate, | 5535 | .msg_queue_associate = selinux_msg_queue_associate, |
5555 | .msg_queue_msgctl = selinux_msg_queue_msgctl, | 5536 | .msg_queue_msgctl = selinux_msg_queue_msgctl, |
5556 | .msg_queue_msgsnd = selinux_msg_queue_msgsnd, | 5537 | .msg_queue_msgsnd = selinux_msg_queue_msgsnd, |
5557 | .msg_queue_msgrcv = selinux_msg_queue_msgrcv, | 5538 | .msg_queue_msgrcv = selinux_msg_queue_msgrcv, |
5558 | 5539 | ||
5559 | .shm_alloc_security = selinux_shm_alloc_security, | 5540 | .shm_alloc_security = selinux_shm_alloc_security, |
5560 | .shm_free_security = selinux_shm_free_security, | 5541 | .shm_free_security = selinux_shm_free_security, |
5561 | .shm_associate = selinux_shm_associate, | 5542 | .shm_associate = selinux_shm_associate, |
5562 | .shm_shmctl = selinux_shm_shmctl, | 5543 | .shm_shmctl = selinux_shm_shmctl, |
5563 | .shm_shmat = selinux_shm_shmat, | 5544 | .shm_shmat = selinux_shm_shmat, |
5564 | 5545 | ||
5565 | .sem_alloc_security = selinux_sem_alloc_security, | 5546 | .sem_alloc_security = selinux_sem_alloc_security, |
5566 | .sem_free_security = selinux_sem_free_security, | 5547 | .sem_free_security = selinux_sem_free_security, |
5567 | .sem_associate = selinux_sem_associate, | 5548 | .sem_associate = selinux_sem_associate, |
5568 | .sem_semctl = selinux_sem_semctl, | 5549 | .sem_semctl = selinux_sem_semctl, |
5569 | .sem_semop = selinux_sem_semop, | 5550 | .sem_semop = selinux_sem_semop, |
5570 | 5551 | ||
5571 | .d_instantiate = selinux_d_instantiate, | 5552 | .d_instantiate = selinux_d_instantiate, |
5572 | 5553 | ||
5573 | .getprocattr = selinux_getprocattr, | 5554 | .getprocattr = selinux_getprocattr, |
5574 | .setprocattr = selinux_setprocattr, | 5555 | .setprocattr = selinux_setprocattr, |
5575 | 5556 | ||
5576 | .secid_to_secctx = selinux_secid_to_secctx, | 5557 | .secid_to_secctx = selinux_secid_to_secctx, |
5577 | .secctx_to_secid = selinux_secctx_to_secid, | 5558 | .secctx_to_secid = selinux_secctx_to_secid, |
5578 | .release_secctx = selinux_release_secctx, | 5559 | .release_secctx = selinux_release_secctx, |
5579 | .inode_notifysecctx = selinux_inode_notifysecctx, | 5560 | .inode_notifysecctx = selinux_inode_notifysecctx, |
5580 | .inode_setsecctx = selinux_inode_setsecctx, | 5561 | .inode_setsecctx = selinux_inode_setsecctx, |
5581 | .inode_getsecctx = selinux_inode_getsecctx, | 5562 | .inode_getsecctx = selinux_inode_getsecctx, |
5582 | 5563 | ||
5583 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5564 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5584 | .unix_may_send = selinux_socket_unix_may_send, | 5565 | .unix_may_send = selinux_socket_unix_may_send, |
5585 | 5566 | ||
5586 | .socket_create = selinux_socket_create, | 5567 | .socket_create = selinux_socket_create, |
5587 | .socket_post_create = selinux_socket_post_create, | 5568 | .socket_post_create = selinux_socket_post_create, |
5588 | .socket_bind = selinux_socket_bind, | 5569 | .socket_bind = selinux_socket_bind, |
5589 | .socket_connect = selinux_socket_connect, | 5570 | .socket_connect = selinux_socket_connect, |
5590 | .socket_listen = selinux_socket_listen, | 5571 | .socket_listen = selinux_socket_listen, |
5591 | .socket_accept = selinux_socket_accept, | 5572 | .socket_accept = selinux_socket_accept, |
5592 | .socket_sendmsg = selinux_socket_sendmsg, | 5573 | .socket_sendmsg = selinux_socket_sendmsg, |
5593 | .socket_recvmsg = selinux_socket_recvmsg, | 5574 | .socket_recvmsg = selinux_socket_recvmsg, |
5594 | .socket_getsockname = selinux_socket_getsockname, | 5575 | .socket_getsockname = selinux_socket_getsockname, |
5595 | .socket_getpeername = selinux_socket_getpeername, | 5576 | .socket_getpeername = selinux_socket_getpeername, |
5596 | .socket_getsockopt = selinux_socket_getsockopt, | 5577 | .socket_getsockopt = selinux_socket_getsockopt, |
5597 | .socket_setsockopt = selinux_socket_setsockopt, | 5578 | .socket_setsockopt = selinux_socket_setsockopt, |
5598 | .socket_shutdown = selinux_socket_shutdown, | 5579 | .socket_shutdown = selinux_socket_shutdown, |
5599 | .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, | 5580 | .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, |
5600 | .socket_getpeersec_stream = selinux_socket_getpeersec_stream, | 5581 | .socket_getpeersec_stream = selinux_socket_getpeersec_stream, |
5601 | .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, | 5582 | .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, |
5602 | .sk_alloc_security = selinux_sk_alloc_security, | 5583 | .sk_alloc_security = selinux_sk_alloc_security, |
5603 | .sk_free_security = selinux_sk_free_security, | 5584 | .sk_free_security = selinux_sk_free_security, |
5604 | .sk_clone_security = selinux_sk_clone_security, | 5585 | .sk_clone_security = selinux_sk_clone_security, |
5605 | .sk_getsecid = selinux_sk_getsecid, | 5586 | .sk_getsecid = selinux_sk_getsecid, |
5606 | .sock_graft = selinux_sock_graft, | 5587 | .sock_graft = selinux_sock_graft, |
5607 | .inet_conn_request = selinux_inet_conn_request, | 5588 | .inet_conn_request = selinux_inet_conn_request, |
5608 | .inet_csk_clone = selinux_inet_csk_clone, | 5589 | .inet_csk_clone = selinux_inet_csk_clone, |
5609 | .inet_conn_established = selinux_inet_conn_established, | 5590 | .inet_conn_established = selinux_inet_conn_established, |
5610 | .secmark_relabel_packet = selinux_secmark_relabel_packet, | 5591 | .secmark_relabel_packet = selinux_secmark_relabel_packet, |
5611 | .secmark_refcount_inc = selinux_secmark_refcount_inc, | 5592 | .secmark_refcount_inc = selinux_secmark_refcount_inc, |
5612 | .secmark_refcount_dec = selinux_secmark_refcount_dec, | 5593 | .secmark_refcount_dec = selinux_secmark_refcount_dec, |
5613 | .req_classify_flow = selinux_req_classify_flow, | 5594 | .req_classify_flow = selinux_req_classify_flow, |
5614 | .tun_dev_create = selinux_tun_dev_create, | 5595 | .tun_dev_create = selinux_tun_dev_create, |
5615 | .tun_dev_post_create = selinux_tun_dev_post_create, | 5596 | .tun_dev_post_create = selinux_tun_dev_post_create, |
5616 | .tun_dev_attach = selinux_tun_dev_attach, | 5597 | .tun_dev_attach = selinux_tun_dev_attach, |
5617 | 5598 | ||
5618 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5599 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5619 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5600 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
5620 | .xfrm_policy_clone_security = selinux_xfrm_policy_clone, | 5601 | .xfrm_policy_clone_security = selinux_xfrm_policy_clone, |
5621 | .xfrm_policy_free_security = selinux_xfrm_policy_free, | 5602 | .xfrm_policy_free_security = selinux_xfrm_policy_free, |
5622 | .xfrm_policy_delete_security = selinux_xfrm_policy_delete, | 5603 | .xfrm_policy_delete_security = selinux_xfrm_policy_delete, |
5623 | .xfrm_state_alloc_security = selinux_xfrm_state_alloc, | 5604 | .xfrm_state_alloc_security = selinux_xfrm_state_alloc, |
5624 | .xfrm_state_free_security = selinux_xfrm_state_free, | 5605 | .xfrm_state_free_security = selinux_xfrm_state_free, |
5625 | .xfrm_state_delete_security = selinux_xfrm_state_delete, | 5606 | .xfrm_state_delete_security = selinux_xfrm_state_delete, |
5626 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, | 5607 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, |
5627 | .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, | 5608 | .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, |
5628 | .xfrm_decode_session = selinux_xfrm_decode_session, | 5609 | .xfrm_decode_session = selinux_xfrm_decode_session, |
5629 | #endif | 5610 | #endif |
5630 | 5611 | ||
5631 | #ifdef CONFIG_KEYS | 5612 | #ifdef CONFIG_KEYS |
5632 | .key_alloc = selinux_key_alloc, | 5613 | .key_alloc = selinux_key_alloc, |
5633 | .key_free = selinux_key_free, | 5614 | .key_free = selinux_key_free, |
5634 | .key_permission = selinux_key_permission, | 5615 | .key_permission = selinux_key_permission, |
5635 | .key_getsecurity = selinux_key_getsecurity, | 5616 | .key_getsecurity = selinux_key_getsecurity, |
5636 | #endif | 5617 | #endif |
5637 | 5618 | ||
5638 | #ifdef CONFIG_AUDIT | 5619 | #ifdef CONFIG_AUDIT |
5639 | .audit_rule_init = selinux_audit_rule_init, | 5620 | .audit_rule_init = selinux_audit_rule_init, |
5640 | .audit_rule_known = selinux_audit_rule_known, | 5621 | .audit_rule_known = selinux_audit_rule_known, |
5641 | .audit_rule_match = selinux_audit_rule_match, | 5622 | .audit_rule_match = selinux_audit_rule_match, |
5642 | .audit_rule_free = selinux_audit_rule_free, | 5623 | .audit_rule_free = selinux_audit_rule_free, |
5643 | #endif | 5624 | #endif |
5644 | }; | 5625 | }; |
5645 | 5626 | ||
5646 | static __init int selinux_init(void) | 5627 | static __init int selinux_init(void) |
5647 | { | 5628 | { |
5648 | if (!security_module_enable(&selinux_ops)) { | 5629 | if (!security_module_enable(&selinux_ops)) { |
5649 | selinux_enabled = 0; | 5630 | selinux_enabled = 0; |
5650 | return 0; | 5631 | return 0; |
5651 | } | 5632 | } |
5652 | 5633 | ||
5653 | if (!selinux_enabled) { | 5634 | if (!selinux_enabled) { |
5654 | printk(KERN_INFO "SELinux: Disabled at boot.\n"); | 5635 | printk(KERN_INFO "SELinux: Disabled at boot.\n"); |
5655 | return 0; | 5636 | return 0; |
5656 | } | 5637 | } |
5657 | 5638 | ||
5658 | printk(KERN_INFO "SELinux: Initializing.\n"); | 5639 | printk(KERN_INFO "SELinux: Initializing.\n"); |
5659 | 5640 | ||
5660 | /* Set the security state for the initial task. */ | 5641 | /* Set the security state for the initial task. */ |
5661 | cred_init_security(); | 5642 | cred_init_security(); |
5662 | 5643 | ||
5663 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | 5644 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); |
5664 | 5645 | ||
5665 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5646 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5666 | sizeof(struct inode_security_struct), | 5647 | sizeof(struct inode_security_struct), |
5667 | 0, SLAB_PANIC, NULL); | 5648 | 0, SLAB_PANIC, NULL); |
5668 | avc_init(); | 5649 | avc_init(); |
5669 | 5650 | ||
5670 | if (register_security(&selinux_ops)) | 5651 | if (register_security(&selinux_ops)) |
5671 | panic("SELinux: Unable to register with kernel.\n"); | 5652 | panic("SELinux: Unable to register with kernel.\n"); |
5672 | 5653 | ||
5673 | if (selinux_enforcing) | 5654 | if (selinux_enforcing) |
5674 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); | 5655 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); |
5675 | else | 5656 | else |
5676 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); | 5657 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); |
5677 | 5658 | ||
5678 | return 0; | 5659 | return 0; |
5679 | } | 5660 | } |
5680 | 5661 | ||
5681 | static void delayed_superblock_init(struct super_block *sb, void *unused) | 5662 | static void delayed_superblock_init(struct super_block *sb, void *unused) |
5682 | { | 5663 | { |
5683 | superblock_doinit(sb, NULL); | 5664 | superblock_doinit(sb, NULL); |
5684 | } | 5665 | } |
5685 | 5666 | ||
5686 | void selinux_complete_init(void) | 5667 | void selinux_complete_init(void) |
5687 | { | 5668 | { |
5688 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5669 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
5689 | 5670 | ||
5690 | /* Set up any superblocks initialized prior to the policy load. */ | 5671 | /* Set up any superblocks initialized prior to the policy load. */ |
5691 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5672 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
5692 | iterate_supers(delayed_superblock_init, NULL); | 5673 | iterate_supers(delayed_superblock_init, NULL); |
5693 | } | 5674 | } |
5694 | 5675 | ||
5695 | /* SELinux requires early initialization in order to label | 5676 | /* SELinux requires early initialization in order to label |
5696 | all processes and objects when they are created. */ | 5677 | all processes and objects when they are created. */ |
5697 | security_initcall(selinux_init); | 5678 | security_initcall(selinux_init); |
5698 | 5679 | ||
5699 | #if defined(CONFIG_NETFILTER) | 5680 | #if defined(CONFIG_NETFILTER) |
5700 | 5681 | ||
5701 | static struct nf_hook_ops selinux_ipv4_ops[] = { | 5682 | static struct nf_hook_ops selinux_ipv4_ops[] = { |
5702 | { | 5683 | { |
5703 | .hook = selinux_ipv4_postroute, | 5684 | .hook = selinux_ipv4_postroute, |
5704 | .owner = THIS_MODULE, | 5685 | .owner = THIS_MODULE, |
5705 | .pf = PF_INET, | 5686 | .pf = PF_INET, |
5706 | .hooknum = NF_INET_POST_ROUTING, | 5687 | .hooknum = NF_INET_POST_ROUTING, |
5707 | .priority = NF_IP_PRI_SELINUX_LAST, | 5688 | .priority = NF_IP_PRI_SELINUX_LAST, |
5708 | }, | 5689 | }, |
5709 | { | 5690 | { |
5710 | .hook = selinux_ipv4_forward, | 5691 | .hook = selinux_ipv4_forward, |
5711 | .owner = THIS_MODULE, | 5692 | .owner = THIS_MODULE, |
5712 | .pf = PF_INET, | 5693 | .pf = PF_INET, |
5713 | .hooknum = NF_INET_FORWARD, | 5694 | .hooknum = NF_INET_FORWARD, |
5714 | .priority = NF_IP_PRI_SELINUX_FIRST, | 5695 | .priority = NF_IP_PRI_SELINUX_FIRST, |
5715 | }, | 5696 | }, |
5716 | { | 5697 | { |
5717 | .hook = selinux_ipv4_output, | 5698 | .hook = selinux_ipv4_output, |
5718 | .owner = THIS_MODULE, | 5699 | .owner = THIS_MODULE, |
5719 | .pf = PF_INET, | 5700 | .pf = PF_INET, |
5720 | .hooknum = NF_INET_LOCAL_OUT, | 5701 | .hooknum = NF_INET_LOCAL_OUT, |
5721 | .priority = NF_IP_PRI_SELINUX_FIRST, | 5702 | .priority = NF_IP_PRI_SELINUX_FIRST, |
5722 | } | 5703 | } |
5723 | }; | 5704 | }; |
5724 | 5705 | ||
5725 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5706 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5726 | 5707 | ||
5727 | static struct nf_hook_ops selinux_ipv6_ops[] = { | 5708 | static struct nf_hook_ops selinux_ipv6_ops[] = { |
5728 | { | 5709 | { |
5729 | .hook = selinux_ipv6_postroute, | 5710 | .hook = selinux_ipv6_postroute, |
5730 | .owner = THIS_MODULE, | 5711 | .owner = THIS_MODULE, |
5731 | .pf = PF_INET6, | 5712 | .pf = PF_INET6, |
5732 | .hooknum = NF_INET_POST_ROUTING, | 5713 | .hooknum = NF_INET_POST_ROUTING, |
5733 | .priority = NF_IP6_PRI_SELINUX_LAST, | 5714 | .priority = NF_IP6_PRI_SELINUX_LAST, |
5734 | }, | 5715 | }, |
5735 | { | 5716 | { |
5736 | .hook = selinux_ipv6_forward, | 5717 | .hook = selinux_ipv6_forward, |
5737 | .owner = THIS_MODULE, | 5718 | .owner = THIS_MODULE, |
5738 | .pf = PF_INET6, | 5719 | .pf = PF_INET6, |
5739 | .hooknum = NF_INET_FORWARD, | 5720 | .hooknum = NF_INET_FORWARD, |
5740 | .priority = NF_IP6_PRI_SELINUX_FIRST, | 5721 | .priority = NF_IP6_PRI_SELINUX_FIRST, |
5741 | } | 5722 | } |
5742 | }; | 5723 | }; |
5743 | 5724 | ||
5744 | #endif /* IPV6 */ | 5725 | #endif /* IPV6 */ |
5745 | 5726 | ||
5746 | static int __init selinux_nf_ip_init(void) | 5727 | static int __init selinux_nf_ip_init(void) |
5747 | { | 5728 | { |
5748 | int err = 0; | 5729 | int err = 0; |
5749 | 5730 | ||
5750 | if (!selinux_enabled) | 5731 | if (!selinux_enabled) |
5751 | goto out; | 5732 | goto out; |
5752 | 5733 | ||
5753 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); | 5734 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); |
5754 | 5735 | ||
5755 | err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); | 5736 | err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5756 | if (err) | 5737 | if (err) |
5757 | panic("SELinux: nf_register_hooks for IPv4: error %d\n", err); | 5738 | panic("SELinux: nf_register_hooks for IPv4: error %d\n", err); |
5758 | 5739 | ||
5759 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5740 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5760 | err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); | 5741 | err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5761 | if (err) | 5742 | if (err) |
5762 | panic("SELinux: nf_register_hooks for IPv6: error %d\n", err); | 5743 | panic("SELinux: nf_register_hooks for IPv6: error %d\n", err); |
5763 | #endif /* IPV6 */ | 5744 | #endif /* IPV6 */ |
5764 | 5745 | ||
5765 | out: | 5746 | out: |
5766 | return err; | 5747 | return err; |
5767 | } | 5748 | } |
5768 | 5749 | ||
5769 | __initcall(selinux_nf_ip_init); | 5750 | __initcall(selinux_nf_ip_init); |
5770 | 5751 | ||
5771 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5752 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5772 | static void selinux_nf_ip_exit(void) | 5753 | static void selinux_nf_ip_exit(void) |
5773 | { | 5754 | { |
5774 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); | 5755 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); |
5775 | 5756 | ||
5776 | nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); | 5757 | nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5777 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5758 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5778 | nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); | 5759 | nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5779 | #endif /* IPV6 */ | 5760 | #endif /* IPV6 */ |
5780 | } | 5761 | } |
5781 | #endif | 5762 | #endif |
5782 | 5763 | ||
5783 | #else /* CONFIG_NETFILTER */ | 5764 | #else /* CONFIG_NETFILTER */ |
5784 | 5765 | ||
5785 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5766 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5786 | #define selinux_nf_ip_exit() | 5767 | #define selinux_nf_ip_exit() |
5787 | #endif | 5768 | #endif |
5788 | 5769 | ||
5789 | #endif /* CONFIG_NETFILTER */ | 5770 | #endif /* CONFIG_NETFILTER */ |
5790 | 5771 | ||
5791 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5772 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5792 | static int selinux_disabled; | 5773 | static int selinux_disabled; |
5793 | 5774 | ||
5794 | int selinux_disable(void) | 5775 | int selinux_disable(void) |
5795 | { | 5776 | { |
5796 | if (ss_initialized) { | 5777 | if (ss_initialized) { |
5797 | /* Not permitted after initial policy load. */ | 5778 | /* Not permitted after initial policy load. */ |
5798 | return -EINVAL; | 5779 | return -EINVAL; |
5799 | } | 5780 | } |
5800 | 5781 | ||
5801 | if (selinux_disabled) { | 5782 | if (selinux_disabled) { |
5802 | /* Only do this once. */ | 5783 | /* Only do this once. */ |
5803 | return -EINVAL; | 5784 | return -EINVAL; |
5804 | } | 5785 | } |
5805 | 5786 | ||
5806 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); | 5787 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); |
5807 | 5788 | ||
5808 | selinux_disabled = 1; | 5789 | selinux_disabled = 1; |
5809 | selinux_enabled = 0; | 5790 | selinux_enabled = 0; |
5810 | 5791 | ||
5811 | reset_security_ops(); | 5792 | reset_security_ops(); |
5812 | 5793 | ||
5813 | /* Try to destroy the avc node cache */ | 5794 | /* Try to destroy the avc node cache */ |
5814 | avc_disable(); | 5795 | avc_disable(); |
5815 | 5796 | ||
5816 | /* Unregister netfilter hooks. */ | 5797 | /* Unregister netfilter hooks. */ |
5817 | selinux_nf_ip_exit(); | 5798 | selinux_nf_ip_exit(); |
5818 | 5799 | ||
5819 | /* Unregister selinuxfs. */ | 5800 | /* Unregister selinuxfs. */ |
5820 | exit_sel_fs(); | 5801 | exit_sel_fs(); |
5821 | 5802 | ||
5822 | return 0; | 5803 | return 0; |
5823 | } | 5804 | } |
5824 | #endif | 5805 | #endif |
5825 | 5806 |