1100894Srwatson/*-
2189503Srwatson * Copyright (c) 1999-2002, 2009 Robert N. M. Watson
3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin
4126262Srwatson * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
5172930Srwatson * Copyright (c) 2006 SPARTA, Inc.
6182063Srwatson * Copyright (c) 2008 Apple Inc.
7100894Srwatson * All rights reserved.
8100894Srwatson *
9100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the
10100894Srwatson * TrustedBSD Project.
11100894Srwatson *
12172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract
13172930Srwatson * N66001-04-C-6019 ("SEFOS").
14172930Srwatson *
15106392Srwatson * This software was developed for the FreeBSD Project in part by Network
16106392Srwatson * Associates Laboratories, the Security Research Division of Network
17106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
18106392Srwatson * as part of the DARPA CHATS research program.
19100894Srwatson *
20189503Srwatson * This software was developed at the University of Cambridge Computer
21189503Srwatson * Laboratory with support from a grant from Google, Inc.
22189503Srwatson *
23100894Srwatson * Redistribution and use in source and binary forms, with or without
24100894Srwatson * modification, are permitted provided that the following conditions
25100894Srwatson * are met:
26100894Srwatson * 1. Redistributions of source code must retain the above copyright
27100894Srwatson *    notice, this list of conditions and the following disclaimer.
28100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright
29100894Srwatson *    notice, this list of conditions and the following disclaimer in the
30100894Srwatson *    documentation and/or other materials provided with the distribution.
31100894Srwatson *
32100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35100894Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42100894Srwatson * SUCH DAMAGE.
43100894Srwatson */
44116182Sobrien
45116182Sobrien#include <sys/cdefs.h>
46116182Sobrien__FBSDID("$FreeBSD$");
47116182Sobrien
48189503Srwatson#include "opt_kdtrace.h"
49100894Srwatson#include "opt_mac.h"
50101173Srwatson
51100894Srwatson#include <sys/param.h>
52100979Srwatson#include <sys/kernel.h>
53100979Srwatson#include <sys/lock.h>
54102949Sbde#include <sys/malloc.h>
55100979Srwatson#include <sys/mutex.h>
56100979Srwatson#include <sys/mac.h>
57164033Srwatson#include <sys/priv.h>
58116701Srwatson#include <sys/sbuf.h>
59189503Srwatson#include <sys/sdt.h>
60100979Srwatson#include <sys/systm.h>
61100979Srwatson#include <sys/mount.h>
62100979Srwatson#include <sys/file.h>
63100979Srwatson#include <sys/namei.h>
64122875Srwatson#include <sys/protosw.h>
65100979Srwatson#include <sys/socket.h>
66100979Srwatson#include <sys/socketvar.h>
67100979Srwatson#include <sys/sysctl.h>
68100894Srwatson
69100979Srwatson#include <net/bpfdesc.h>
70100979Srwatson#include <net/if.h>
71100979Srwatson#include <net/if_var.h>
72100979Srwatson
73163606Srwatson#include <security/mac/mac_framework.h>
74121357Srwatson#include <security/mac/mac_internal.h>
75165469Srwatson#include <security/mac/mac_policy.h>
76100979Srwatson
77126262Srwatson/*
78165423Srwatson * XXXRW: struct ifnet locking is incomplete in the network code, so we use
79165423Srwatson * our own global mutex for struct ifnet.  Non-ideal, but should help in the
80165423Srwatson * SMP environment.
81131025Srwatson */
82173095Srwatsonstruct mtx mac_ifnet_mtx;
83131025SrwatsonMTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
84131025Srwatson
85165423Srwatson/*
86165423Srwatson * Retrieve the label associated with an mbuf by searching for the tag.
87165423Srwatson * Depending on the value of mac_labelmbufs, it's possible that a label will
88165423Srwatson * not be present, in which case NULL is returned.  Policies must handle the
89165423Srwatson * possibility of an mbuf not having label storage if they do not enforce
90165423Srwatson * early loading.
91165423Srwatson */
92126262Srwatsonstruct label *
93168955Srwatsonmac_mbuf_to_label(struct mbuf *m)
94113482Srwatson{
95113487Srwatson	struct m_tag *tag;
96113482Srwatson	struct label *label;
97113482Srwatson
98168955Srwatson	if (m == NULL)
99128902Srwatson		return (NULL);
100168955Srwatson	tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL);
101128902Srwatson	if (tag == NULL)
102128902Srwatson		return (NULL);
103113487Srwatson	label = (struct label *)(tag+1);
104113482Srwatson	return (label);
105113482Srwatson}
106113482Srwatson
107122524Srwatsonstatic struct label *
108122524Srwatsonmac_bpfdesc_label_alloc(void)
109122524Srwatson{
110122524Srwatson	struct label *label;
111122524Srwatson
112122524Srwatson	label = mac_labelzone_alloc(M_WAITOK);
113191731Srwatson	MAC_POLICY_PERFORM(bpfdesc_init_label, label);
114122524Srwatson	return (label);
115122524Srwatson}
116122524Srwatson
117100979Srwatsonvoid
118172930Srwatsonmac_bpfdesc_init(struct bpf_d *d)
119104521Srwatson{
120104521Srwatson
121182063Srwatson	if (mac_labeled & MPC_OBJECT_BPFDESC)
122182063Srwatson		d->bd_label = mac_bpfdesc_label_alloc();
123182063Srwatson	else
124182063Srwatson		d->bd_label = NULL;
125104521Srwatson}
126104521Srwatson
127122524Srwatsonstatic struct label *
128122524Srwatsonmac_ifnet_label_alloc(void)
129104521Srwatson{
130122524Srwatson	struct label *label;
131104521Srwatson
132122524Srwatson	label = mac_labelzone_alloc(M_WAITOK);
133191731Srwatson	MAC_POLICY_PERFORM(ifnet_init_label, label);
134122524Srwatson	return (label);
135104521Srwatson}
136104521Srwatson
137104521Srwatsonvoid
138172930Srwatsonmac_ifnet_init(struct ifnet *ifp)
139105694Srwatson{
140105694Srwatson
141182063Srwatson	if (mac_labeled & MPC_OBJECT_IFNET)
142182063Srwatson		ifp->if_label = mac_ifnet_label_alloc();
143182063Srwatson	else
144182063Srwatson		ifp->if_label = NULL;
145105694Srwatson}
146105694Srwatson
147122875Srwatsonint
148172930Srwatsonmac_mbuf_tag_init(struct m_tag *tag, int flag)
149104527Srwatson{
150113487Srwatson	struct label *label;
151113526Srwatson	int error;
152104528Srwatson
153113487Srwatson	label = (struct label *) (tag + 1);
154113487Srwatson	mac_init_label(label);
155104527Srwatson
156189797Srwatson	if (flag & M_WAITOK)
157191731Srwatson		MAC_POLICY_CHECK(mbuf_init_label, label, flag);
158189797Srwatson	else
159191731Srwatson		MAC_POLICY_CHECK_NOSLEEP(mbuf_init_label, label, flag);
160104528Srwatson	if (error) {
161191731Srwatson		MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
162113487Srwatson		mac_destroy_label(label);
163104528Srwatson	}
164104528Srwatson	return (error);
165104527Srwatson}
166104527Srwatson
167113487Srwatsonint
168172930Srwatsonmac_mbuf_init(struct mbuf *m, int flag)
169113487Srwatson{
170113487Srwatson	struct m_tag *tag;
171113487Srwatson	int error;
172113487Srwatson
173113487Srwatson	M_ASSERTPKTHDR(m);
174113487Srwatson
175182063Srwatson	if (mac_labeled & MPC_OBJECT_MBUF) {
176182063Srwatson		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
177182063Srwatson		    flag);
178182063Srwatson		if (tag == NULL)
179182063Srwatson			return (ENOMEM);
180182063Srwatson		error = mac_mbuf_tag_init(tag, flag);
181182063Srwatson		if (error) {
182182063Srwatson			m_tag_free(tag);
183182063Srwatson			return (error);
184182063Srwatson		}
185182063Srwatson		m_tag_prepend(m, tag);
186113487Srwatson	}
187113487Srwatson	return (0);
188113487Srwatson}
189113487Srwatson
190122524Srwatsonstatic void
191122524Srwatsonmac_bpfdesc_label_free(struct label *label)
192122524Srwatson{
193104541Srwatson
194191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_destroy_label, label);
195122524Srwatson	mac_labelzone_free(label);
196104541Srwatson}
197104541Srwatson
198105988Srwatsonvoid
199172930Srwatsonmac_bpfdesc_destroy(struct bpf_d *d)
200104521Srwatson{
201104521Srwatson
202182063Srwatson	if (d->bd_label != NULL) {
203182063Srwatson		mac_bpfdesc_label_free(d->bd_label);
204182063Srwatson		d->bd_label = NULL;
205182063Srwatson	}
206104521Srwatson}
207104521Srwatson
208105694Srwatsonstatic void
209122524Srwatsonmac_ifnet_label_free(struct label *label)
210104521Srwatson{
211104521Srwatson
212191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(ifnet_destroy_label, label);
213122524Srwatson	mac_labelzone_free(label);
214104521Srwatson}
215104521Srwatson
216104521Srwatsonvoid
217172930Srwatsonmac_ifnet_destroy(struct ifnet *ifp)
218105694Srwatson{
219105694Srwatson
220182063Srwatson	if (ifp->if_label != NULL) {
221182063Srwatson		mac_ifnet_label_free(ifp->if_label);
222182063Srwatson		ifp->if_label = NULL;
223182063Srwatson	}
224105694Srwatson}
225105694Srwatson
226122875Srwatsonvoid
227172930Srwatsonmac_mbuf_tag_destroy(struct m_tag *tag)
228104521Srwatson{
229113487Srwatson	struct label *label;
230104521Srwatson
231113487Srwatson	label = (struct label *)(tag+1);
232113487Srwatson
233191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
234113487Srwatson	mac_destroy_label(label);
235104521Srwatson}
236104521Srwatson
237165423Srwatson/*
238172930Srwatson * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which
239165423Srwatson * case the labels must also be duplicated.
240165423Srwatson */
241122820Srwatsonvoid
242172930Srwatsonmac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest)
243113487Srwatson{
244113487Srwatson	struct label *src_label, *dest_label;
245113487Srwatson
246113487Srwatson	src_label = (struct label *)(src+1);
247113487Srwatson	dest_label = (struct label *)(dest+1);
248113487Srwatson
249113487Srwatson	/*
250172930Srwatson	 * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(),
251165423Srwatson	 * so we don't need to call it here.
252113487Srwatson	 */
253191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
254113487Srwatson}
255113487Srwatson
256147785Srwatsonvoid
257172930Srwatsonmac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to)
258147785Srwatson{
259147785Srwatson	struct label *src_label, *dest_label;
260147785Srwatson
261193393Srwatson	if (mac_policy_count == 0)
262193393Srwatson		return;
263193393Srwatson
264147785Srwatson	src_label = mac_mbuf_to_label(m_from);
265147785Srwatson	dest_label = mac_mbuf_to_label(m_to);
266147785Srwatson
267191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
268147785Srwatson}
269147785Srwatson
270131025Srwatsonstatic void
271172930Srwatsonmac_ifnet_copy_label(struct label *src, struct label *dest)
272131025Srwatson{
273131025Srwatson
274191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(ifnet_copy_label, src, dest);
275131025Srwatson}
276131025Srwatson
277104522Srwatsonstatic int
278172930Srwatsonmac_ifnet_externalize_label(struct label *label, char *elements,
279122159Srwatson    char *outbuf, size_t outbuflen)
280104522Srwatson{
281104522Srwatson	int error;
282104522Srwatson
283191731Srwatson	MAC_POLICY_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
284104522Srwatson
285104522Srwatson	return (error);
286104522Srwatson}
287104522Srwatson
288105694Srwatsonstatic int
289172930Srwatsonmac_ifnet_internalize_label(struct label *label, char *string)
290105694Srwatson{
291105694Srwatson	int error;
292105694Srwatson
293191731Srwatson	MAC_POLICY_INTERNALIZE(ifnet, label, string);
294105694Srwatson
295105694Srwatson	return (error);
296105694Srwatson}
297105694Srwatson
298104521Srwatsonvoid
299172930Srwatsonmac_ifnet_create(struct ifnet *ifp)
300100979Srwatson{
301100979Srwatson
302193391Srwatson	if (mac_policy_count == 0)
303193391Srwatson		return;
304193391Srwatson
305168955Srwatson	MAC_IFNET_LOCK(ifp);
306191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label);
307168955Srwatson	MAC_IFNET_UNLOCK(ifp);
308100979Srwatson}
309100979Srwatson
310100979Srwatsonvoid
311172930Srwatsonmac_bpfdesc_create(struct ucred *cred, struct bpf_d *d)
312100979Srwatson{
313100979Srwatson
314191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label);
315100979Srwatson}
316100979Srwatson
317100979Srwatsonvoid
318172930Srwatsonmac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
319100979Srwatson{
320113482Srwatson	struct label *label;
321100979Srwatson
322247629Smelifaro	/* Assume reader lock is enough. */
323168955Srwatson	BPFD_LOCK_ASSERT(d);
324126406Srwatson
325193391Srwatson	if (mac_policy_count == 0)
326193391Srwatson		return;
327193391Srwatson
328168955Srwatson	label = mac_mbuf_to_label(m);
329113482Srwatson
330191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m,
331191731Srwatson	    label);
332100979Srwatson}
333100979Srwatson
334100979Srwatsonvoid
335172930Srwatsonmac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m)
336100979Srwatson{
337113482Srwatson	struct label *label;
338100979Srwatson
339193391Srwatson	if (mac_policy_count == 0)
340193391Srwatson		return;
341193391Srwatson
342168955Srwatson	label = mac_mbuf_to_label(m);
343113482Srwatson
344168955Srwatson	MAC_IFNET_LOCK(ifp);
345191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, ifp->if_label, m,
346191731Srwatson	    label);
347168955Srwatson	MAC_IFNET_UNLOCK(ifp);
348100979Srwatson}
349100979Srwatson
350189503SrwatsonMAC_CHECK_PROBE_DEFINE2(bpfdesc_check_receive, "struct bpf_d *",
351189503Srwatson    "struct ifnet *");
352189503Srwatson
353100979Srwatsonint
354172930Srwatsonmac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
355100979Srwatson{
356100979Srwatson	int error;
357100979Srwatson
358247629Smelifaro	/* Assume reader lock is enough. */
359168955Srwatson	BPFD_LOCK_ASSERT(d);
360126406Srwatson
361193391Srwatson	if (mac_policy_count == 0)
362193391Srwatson		return (0);
363193391Srwatson
364168955Srwatson	MAC_IFNET_LOCK(ifp);
365191731Srwatson	MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp,
366189797Srwatson	    ifp->if_label);
367189503Srwatson	MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp);
368168955Srwatson	MAC_IFNET_UNLOCK(ifp);
369100979Srwatson
370100979Srwatson	return (error);
371100979Srwatson}
372100979Srwatson
373189503SrwatsonMAC_CHECK_PROBE_DEFINE2(ifnet_check_transmit, "struct ifnet *",
374189503Srwatson    "struct mbuf *");
375189503Srwatson
376100979Srwatsonint
377172930Srwatsonmac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m)
378100979Srwatson{
379113482Srwatson	struct label *label;
380100979Srwatson	int error;
381100979Srwatson
382168955Srwatson	M_ASSERTPKTHDR(m);
383113487Srwatson
384193391Srwatson	if (mac_policy_count == 0)
385193391Srwatson		return (0);
386193391Srwatson
387168955Srwatson	label = mac_mbuf_to_label(m);
388100979Srwatson
389168955Srwatson	MAC_IFNET_LOCK(ifp);
390191731Srwatson	MAC_POLICY_CHECK_NOSLEEP(ifnet_check_transmit, ifp, ifp->if_label, m,
391189797Srwatson	    label);
392189503Srwatson	MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m);
393168955Srwatson	MAC_IFNET_UNLOCK(ifp);
394100979Srwatson
395100979Srwatson	return (error);
396100979Srwatson}
397100979Srwatson
398100979Srwatsonint
399172930Srwatsonmac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr,
400168955Srwatson    struct ifnet *ifp)
401100979Srwatson{
402105694Srwatson	char *elements, *buffer;
403131025Srwatson	struct label *intlabel;
404105694Srwatson	struct mac mac;
405100979Srwatson	int error;
406100979Srwatson
407182063Srwatson	if (!(mac_labeled & MPC_OBJECT_IFNET))
408182063Srwatson		return (EINVAL);
409182063Srwatson
410105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
411100979Srwatson	if (error)
412100979Srwatson		return (error);
413100979Srwatson
414105694Srwatson	error = mac_check_structmac_consistent(&mac);
415105694Srwatson	if (error)
416105694Srwatson		return (error);
417105694Srwatson
418111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
419105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
420105694Srwatson	if (error) {
421105694Srwatson		free(elements, M_MACTEMP);
422105694Srwatson		return (error);
423105694Srwatson	}
424105694Srwatson
425111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
426131025Srwatson	intlabel = mac_ifnet_label_alloc();
427168955Srwatson	MAC_IFNET_LOCK(ifp);
428172930Srwatson	mac_ifnet_copy_label(ifp->if_label, intlabel);
429168955Srwatson	MAC_IFNET_UNLOCK(ifp);
430172930Srwatson	error = mac_ifnet_externalize_label(intlabel, elements, buffer,
431165412Srwatson	    mac.m_buflen);
432131025Srwatson	mac_ifnet_label_free(intlabel);
433105694Srwatson	if (error == 0)
434105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
435105694Srwatson
436105694Srwatson	free(buffer, M_MACTEMP);
437105694Srwatson	free(elements, M_MACTEMP);
438105694Srwatson
439105694Srwatson	return (error);
440100979Srwatson}
441100979Srwatson
442100979Srwatsonint
443172930Srwatsonmac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp)
444100979Srwatson{
445122524Srwatson	struct label *intlabel;
446105694Srwatson	struct mac mac;
447105694Srwatson	char *buffer;
448100979Srwatson	int error;
449100979Srwatson
450182063Srwatson	if (!(mac_labeled & MPC_OBJECT_IFNET))
451182063Srwatson		return (EINVAL);
452182063Srwatson
453105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
454100979Srwatson	if (error)
455100979Srwatson		return (error);
456100979Srwatson
457105694Srwatson	error = mac_check_structmac_consistent(&mac);
458100979Srwatson	if (error)
459100979Srwatson		return (error);
460100979Srwatson
461111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
462105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
463105694Srwatson	if (error) {
464105694Srwatson		free(buffer, M_MACTEMP);
465105694Srwatson		return (error);
466105694Srwatson	}
467105694Srwatson
468122524Srwatson	intlabel = mac_ifnet_label_alloc();
469172930Srwatson	error = mac_ifnet_internalize_label(intlabel, buffer);
470105694Srwatson	free(buffer, M_MACTEMP);
471105694Srwatson	if (error) {
472122524Srwatson		mac_ifnet_label_free(intlabel);
473105694Srwatson		return (error);
474105694Srwatson	}
475105694Srwatson
476100979Srwatson	/*
477164033Srwatson	 * XXX: Note that this is a redundant privilege check, since policies
478165423Srwatson	 * impose this check themselves if required by the policy
479164033Srwatson	 * Eventually, this should go away.
480100979Srwatson	 */
481164033Srwatson	error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
482105694Srwatson	if (error) {
483122524Srwatson		mac_ifnet_label_free(intlabel);
484105694Srwatson		return (error);
485105694Srwatson	}
486100979Srwatson
487168955Srwatson	MAC_IFNET_LOCK(ifp);
488191731Srwatson	MAC_POLICY_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp,
489191731Srwatson	    ifp->if_label, intlabel);
490105694Srwatson	if (error) {
491168955Srwatson		MAC_IFNET_UNLOCK(ifp);
492122524Srwatson		mac_ifnet_label_free(intlabel);
493105694Srwatson		return (error);
494105694Srwatson	}
495100979Srwatson
496191731Srwatson	MAC_POLICY_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, ifp->if_label,
497189797Srwatson	    intlabel);
498168955Srwatson	MAC_IFNET_UNLOCK(ifp);
499100979Srwatson
500122524Srwatson	mac_ifnet_label_free(intlabel);
501105694Srwatson	return (0);
502100979Srwatson}
503