]>
Commit | Line | Data |
---|---|---|
2d21ac55 A |
1 | /* |
2 | * Copyright (c) 2007 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
0a7de745 | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
0a7de745 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
2d21ac55 A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
0a7de745 | 25 | * |
2d21ac55 A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
28 | #include <sys/param.h> | |
29 | #include <sys/vnode.h> | |
30 | #include <sys/vnode_internal.h> | |
31 | #include <sys/kauth.h> | |
32 | #include <sys/namei.h> | |
33 | #include <sys/mount.h> | |
34 | #include <sys/mount_internal.h> | |
35 | #include <sys/uio_internal.h> | |
36 | #include <sys/xattr.h> | |
b0d623f7 | 37 | #include "../bsd/sys/fsevents.h" |
2d21ac55 A |
38 | |
39 | #include <security/mac_internal.h> | |
40 | ||
41 | /* | |
b0d623f7 | 42 | * Caller holds I/O reference on vnode |
2d21ac55 A |
43 | */ |
44 | int | |
45 | vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp, | |
0a7de745 | 46 | struct componentname *cnp, int flags, vfs_context_t ctx) |
2d21ac55 | 47 | { |
b0d623f7 | 48 | int error = 0; |
2d21ac55 | 49 | |
2d21ac55 | 50 | |
b0d623f7 | 51 | /* fast path checks... */ |
2d21ac55 | 52 | |
b0d623f7 A |
53 | /* are we labeling vnodes? If not still notify of create */ |
54 | if (mac_label_vnodes == 0) { | |
0a7de745 | 55 | if (flags & VNODE_LABEL_CREATE) { |
b0d623f7 A |
56 | error = mac_vnode_notify_create(ctx, |
57 | mp, dvp, vp, cnp); | |
0a7de745 | 58 | } |
b0d623f7 | 59 | return 0; |
2d21ac55 A |
60 | } |
61 | ||
b0d623f7 | 62 | /* if already VL_LABELED */ |
0a7de745 A |
63 | if (vp->v_lflag & VL_LABELED) { |
64 | return 0; | |
65 | } | |
b0d623f7 A |
66 | |
67 | vnode_lock_spin(vp); | |
68 | ||
69 | /* | |
70 | * must revalidate state once we hold the lock | |
71 | * since we could have blocked and someone else | |
72 | * has since labeled this vnode | |
73 | */ | |
74 | if (vp->v_lflag & VL_LABELED) { | |
2d21ac55 | 75 | vnode_unlock(vp); |
0a7de745 | 76 | return 0; |
2d21ac55 A |
77 | } |
78 | ||
79 | if ((vp->v_lflag & VL_LABEL) == 0) { | |
80 | vp->v_lflag |= VL_LABEL; | |
81 | ||
82 | /* Could sleep on disk I/O, drop lock. */ | |
83 | vnode_unlock(vp); | |
b0d623f7 | 84 | |
0a7de745 | 85 | if (vp->v_label == NULL) { |
b0d623f7 | 86 | vp->v_label = mac_vnode_label_alloc(); |
0a7de745 | 87 | } |
b0d623f7 | 88 | |
0a7de745 | 89 | if (flags & VNODE_LABEL_CREATE) { |
2d21ac55 A |
90 | error = mac_vnode_notify_create(ctx, |
91 | mp, dvp, vp, cnp); | |
0a7de745 | 92 | } else { |
2d21ac55 | 93 | error = mac_vnode_label_associate(mp, vp, ctx); |
0a7de745 | 94 | } |
b0d623f7 A |
95 | |
96 | vnode_lock_spin(vp); | |
2d21ac55 | 97 | |
0a7de745 | 98 | if ((error == 0) && (vp->v_flag & VNCACHEABLE)) { |
2d21ac55 | 99 | vp->v_lflag |= VL_LABELED; |
0a7de745 | 100 | } |
2d21ac55 A |
101 | vp->v_lflag &= ~VL_LABEL; |
102 | ||
103 | if (vp->v_lflag & VL_LABELWAIT) { | |
104 | vp->v_lflag &= ~VL_LABELWAIT; | |
b0d623f7 | 105 | wakeup(&vp->v_label); |
2d21ac55 | 106 | } |
2d21ac55 A |
107 | } else { |
108 | struct timespec ts; | |
109 | ||
110 | ts.tv_sec = 10; | |
111 | ts.tv_nsec = 0; | |
112 | ||
113 | while (vp->v_lflag & VL_LABEL) { | |
114 | vp->v_lflag |= VL_LABELWAIT; | |
b0d623f7 | 115 | |
0a7de745 A |
116 | error = msleep(&vp->v_label, &vp->v_lock, PVFS | PDROP, |
117 | "vnode_label", &ts); | |
b0d623f7 A |
118 | vnode_lock_spin(vp); |
119 | ||
2d21ac55 A |
120 | if (error == EWOULDBLOCK) { |
121 | vprint("vnode label timeout", vp); | |
122 | break; | |
123 | } | |
124 | } | |
125 | /* XXX: what should be done if labeling failed (above)? */ | |
2d21ac55 | 126 | } |
b0d623f7 | 127 | vnode_unlock(vp); |
2d21ac55 | 128 | |
0a7de745 | 129 | return error; |
2d21ac55 A |
130 | } |
131 | ||
132 | ||
133 | /* | |
134 | * Clear the "labeled" flag on a VNODE. | |
135 | * VNODE will have label re-associated upon | |
136 | * next call to lookup(). | |
137 | * | |
138 | * Caller verifies vfs_flags(vnode_mount(vp)) & MNT_MULTILABEL | |
139 | * Caller holds vnode lock. | |
140 | */ | |
141 | void | |
142 | vnode_relabel(struct vnode *vp) | |
143 | { | |
2d21ac55 A |
144 | /* Wait for any other labeling to complete. */ |
145 | while (vp->v_lflag & VL_LABEL) { | |
146 | vp->v_lflag |= VL_LABELWAIT; | |
b0d623f7 | 147 | (void)msleep(&vp->v_label, &vp->v_lock, PVFS, "vnode_relabel", 0); |
2d21ac55 A |
148 | } |
149 | ||
150 | /* Clear labeled flag */ | |
151 | vp->v_lflag &= ~VL_LABELED; | |
152 | ||
153 | return; | |
154 | } | |
155 | ||
156 | /* | |
157 | * VFS XATTR helpers. | |
158 | */ | |
159 | ||
160 | int | |
0a7de745 | 161 | mac_vnop_setxattr(struct vnode *vp, const char *name, char *buf, size_t len) |
2d21ac55 A |
162 | { |
163 | vfs_context_t ctx; | |
164 | int options = XATTR_NOSECURITY; | |
0a7de745 A |
165 | char uio_buf[UIO_SIZEOF(1)]; |
166 | uio_t auio; | |
2d21ac55 A |
167 | int error; |
168 | ||
0a7de745 A |
169 | if (vfs_isrdonly(vp->v_mount)) { |
170 | return EROFS; | |
171 | } | |
2d21ac55 A |
172 | |
173 | ctx = vfs_context_current(); | |
174 | auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_WRITE, | |
0a7de745 | 175 | &uio_buf[0], sizeof(uio_buf)); |
2d21ac55 A |
176 | uio_addiov(auio, CAST_USER_ADDR_T(buf), len); |
177 | ||
178 | error = vn_setxattr(vp, name, auio, options, ctx); | |
b0d623f7 A |
179 | #if CONFIG_FSE |
180 | if (error == 0) { | |
181 | add_fsevent(FSE_XATTR_MODIFIED, ctx, | |
182 | FSE_ARG_VNODE, vp, | |
183 | FSE_ARG_DONE); | |
184 | } | |
185 | #endif | |
2d21ac55 | 186 | |
0a7de745 | 187 | return error; |
2d21ac55 A |
188 | } |
189 | ||
190 | int | |
0a7de745 A |
191 | mac_vnop_getxattr(struct vnode *vp, const char *name, char *buf, size_t len, |
192 | size_t *attrlen) | |
2d21ac55 A |
193 | { |
194 | vfs_context_t ctx = vfs_context_current(); | |
195 | int options = XATTR_NOSECURITY; | |
0a7de745 A |
196 | char uio_buf[UIO_SIZEOF(1)]; |
197 | uio_t auio; | |
2d21ac55 A |
198 | int error; |
199 | ||
200 | auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, | |
0a7de745 | 201 | &uio_buf[0], sizeof(uio_buf)); |
2d21ac55 A |
202 | uio_addiov(auio, CAST_USER_ADDR_T(buf), len); |
203 | ||
204 | error = vn_getxattr(vp, name, auio, attrlen, options, ctx); | |
205 | *attrlen = len - uio_resid(auio); | |
206 | ||
0a7de745 | 207 | return error; |
2d21ac55 A |
208 | } |
209 | ||
210 | int | |
0a7de745 | 211 | mac_vnop_removexattr(struct vnode *vp, const char *name) |
2d21ac55 A |
212 | { |
213 | vfs_context_t ctx = vfs_context_current(); | |
214 | int options = XATTR_NOSECURITY; | |
215 | int error; | |
216 | ||
0a7de745 A |
217 | if (vfs_isrdonly(vp->v_mount)) { |
218 | return EROFS; | |
219 | } | |
2d21ac55 A |
220 | |
221 | error = vn_removexattr(vp, name, options, ctx); | |
b0d623f7 A |
222 | #if CONFIG_FSE |
223 | if (error == 0) { | |
224 | add_fsevent(FSE_XATTR_REMOVED, ctx, | |
225 | FSE_ARG_VNODE, vp, | |
226 | FSE_ARG_DONE); | |
227 | } | |
228 | #endif | |
2d21ac55 | 229 | |
0a7de745 | 230 | return error; |
2d21ac55 | 231 | } |