Print this page
3665 Implement O_CLOEXEC as an open() flag
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/syscall/open.c
+++ new/usr/src/uts/common/syscall/open.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 27 /* All Rights Reserved */
28 28
29 29 /*
30 + * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
31 + */
32 +/*
30 33 * Portions of this source code were derived from Berkeley 4.3 BSD
31 34 * under license from the Regents of the University of California.
32 35 */
33 36
34 37 #include <sys/param.h>
35 38 #include <sys/isa_defs.h>
36 39 #include <sys/types.h>
37 40 #include <sys/sysmacros.h>
38 41 #include <sys/user.h>
39 42 #include <sys/systm.h>
40 43 #include <sys/errno.h>
41 44 #include <sys/fcntl.h>
42 45 #include <sys/stat.h>
43 46 #include <sys/vnode.h>
44 47 #include <sys/vfs.h>
45 48 #include <sys/file.h>
46 49 #include <sys/mode.h>
47 50 #include <sys/uio.h>
48 51 #include <sys/debug.h>
49 52 #include <c2/audit.h>
50 53
51 54 /*
52 55 * Common code for openat(). Check permissions, allocate an open
53 56 * file structure, and call the device open routine (if any).
54 57 */
55 58
56 59 static int
57 60 copen(int startfd, char *fname, int filemode, int createmode)
58 61 {
59 62 struct pathname pn;
60 63 vnode_t *vp, *sdvp;
61 64 file_t *fp, *startfp;
62 65 enum vtype type;
63 66 int error;
64 67 int fd, dupfd;
65 68 vnode_t *startvp;
66 69 proc_t *p = curproc;
67 70 uio_seg_t seg = UIO_USERSPACE;
68 71 char *open_filename = fname;
69 72 uint32_t auditing = AU_AUDITING();
70 73 char startchar;
71 74
72 75 if (filemode & (FSEARCH|FEXEC)) {
73 76 /*
74 77 * Must be one or the other and neither FREAD nor FWRITE
75 78 * Must not be any of FAPPEND FCREAT FTRUNC FXATTR FXATTRDIROPEN
76 79 * XXX: Should these just be silently ignored?
77 80 */
78 81 if ((filemode & (FREAD|FWRITE)) ||
79 82 (filemode & (FSEARCH|FEXEC)) == (FSEARCH|FEXEC) ||
80 83 (filemode & (FAPPEND|FCREAT|FTRUNC|FXATTR|FXATTRDIROPEN)))
81 84 return (set_errno(EINVAL));
82 85 }
83 86
84 87 if (startfd == AT_FDCWD) {
85 88 /*
86 89 * Regular open()
87 90 */
88 91 startvp = NULL;
89 92 } else {
90 93 /*
91 94 * We're here via openat()
92 95 */
93 96 if (copyin(fname, &startchar, sizeof (char)))
94 97 return (set_errno(EFAULT));
95 98
96 99 /*
97 100 * if startchar is / then startfd is ignored
98 101 */
99 102 if (startchar == '/')
100 103 startvp = NULL;
101 104 else {
102 105 if ((startfp = getf(startfd)) == NULL)
103 106 return (set_errno(EBADF));
104 107 startvp = startfp->f_vnode;
105 108 VN_HOLD(startvp);
106 109 releasef(startfd);
107 110 }
108 111 }
109 112
110 113 /*
111 114 * Handle __openattrdirat() requests
112 115 */
113 116 if (filemode & FXATTRDIROPEN) {
114 117 if (auditing && startvp != NULL)
115 118 audit_setfsat_path(1);
116 119 if (error = lookupnameat(fname, seg, FOLLOW,
117 120 NULLVPP, &vp, startvp))
118 121 return (set_errno(error));
119 122 if (startvp != NULL)
120 123 VN_RELE(startvp);
121 124
122 125 startvp = vp;
123 126 }
124 127
125 128 /*
126 129 * Do we need to go into extended attribute space?
127 130 */
128 131 if (filemode & FXATTR) {
129 132 if (startfd == AT_FDCWD) {
130 133 if (copyin(fname, &startchar, sizeof (char)))
131 134 return (set_errno(EFAULT));
132 135
133 136 /*
134 137 * If startchar == '/' then no extended attributes
135 138 * are looked up.
136 139 */
137 140 if (startchar == '/') {
138 141 startvp = NULL;
139 142 } else {
140 143 mutex_enter(&p->p_lock);
141 144 startvp = PTOU(p)->u_cdir;
142 145 VN_HOLD(startvp);
143 146 mutex_exit(&p->p_lock);
144 147 }
145 148 }
146 149
147 150 /*
148 151 * Make sure we have a valid extended attribute request.
149 152 * We must either have a real fd or AT_FDCWD and a relative
150 153 * pathname.
151 154 */
152 155 if (startvp == NULL) {
153 156 goto noxattr;
154 157 }
155 158 }
156 159
157 160 if (filemode & (FXATTR|FXATTRDIROPEN)) {
158 161 vattr_t vattr;
159 162
160 163 if (error = pn_get(fname, UIO_USERSPACE, &pn)) {
161 164 goto out;
162 165 }
163 166
164 167 /*
165 168 * In order to access hidden attribute directory the
166 169 * user must be able to stat() the file
167 170 */
168 171 vattr.va_mask = AT_ALL;
169 172 if (error = VOP_GETATTR(startvp, &vattr, 0, CRED(), NULL)) {
170 173 pn_free(&pn);
171 174 goto out;
172 175 }
173 176
174 177 if ((startvp->v_vfsp->vfs_flag & VFS_XATTR) != 0 ||
175 178 vfs_has_feature(startvp->v_vfsp, VFSFT_SYSATTR_VIEWS)) {
176 179 error = VOP_LOOKUP(startvp, "", &sdvp, &pn,
177 180 (filemode & FXATTRDIROPEN) ? LOOKUP_XATTR :
178 181 LOOKUP_XATTR|CREATE_XATTR_DIR, rootvp, CRED(),
179 182 NULL, NULL, NULL);
180 183 } else {
181 184 error = EINVAL;
182 185 }
183 186
184 187 /*
185 188 * For __openattrdirat() use "." as filename to open
186 189 * as part of vn_openat()
187 190 */
188 191 if (error == 0 && (filemode & FXATTRDIROPEN)) {
189 192 open_filename = ".";
190 193 seg = UIO_SYSSPACE;
191 194 }
192 195
193 196 pn_free(&pn);
194 197 if (error != 0)
195 198 goto out;
196 199
197 200 VN_RELE(startvp);
198 201 startvp = sdvp;
199 202 }
200 203
201 204 noxattr:
202 205 if ((filemode & (FREAD|FWRITE|FSEARCH|FEXEC|FXATTRDIROPEN)) != 0) {
203 206 if ((filemode & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY))
204 207 filemode &= ~FNDELAY;
205 208 error = falloc((vnode_t *)NULL, filemode, &fp, &fd);
206 209 if (error == 0) {
207 210 if (auditing && startvp != NULL)
208 211 audit_setfsat_path(1);
209 212 /*
210 213 * Last arg is a don't-care term if
211 214 * !(filemode & FCREAT).
212 215 */
213 216 error = vn_openat(open_filename, seg, filemode,
214 217 (int)(createmode & MODEMASK),
215 218 &vp, CRCREAT, PTOU(curproc)->u_cmask,
216 219 startvp, fd);
217 220
218 221 if (startvp != NULL)
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
219 222 VN_RELE(startvp);
220 223 if (error == 0) {
221 224 if ((vp->v_flag & VDUP) == 0) {
222 225 fp->f_vnode = vp;
223 226 mutex_exit(&fp->f_tlock);
224 227 /*
225 228 * We must now fill in the slot
226 229 * falloc reserved.
227 230 */
228 231 setf(fd, fp);
232 + if ((filemode & FCLOEXEC) != 0) {
233 + f_setfd(fd, FD_CLOEXEC);
234 + }
229 235 return (fd);
230 236 } else {
231 237 /*
232 238 * Special handling for /dev/fd.
233 239 * Give up the file pointer
234 240 * and dup the indicated file descriptor
235 241 * (in v_rdev). This is ugly, but I've
236 242 * seen worse.
237 243 */
238 244 unfalloc(fp);
239 245 dupfd = getminor(vp->v_rdev);
240 246 type = vp->v_type;
241 247 mutex_enter(&vp->v_lock);
242 248 vp->v_flag &= ~VDUP;
243 249 mutex_exit(&vp->v_lock);
244 250 VN_RELE(vp);
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
245 251 if (type != VCHR)
246 252 return (set_errno(EINVAL));
247 253 if ((fp = getf(dupfd)) == NULL) {
248 254 setf(fd, NULL);
249 255 return (set_errno(EBADF));
250 256 }
251 257 mutex_enter(&fp->f_tlock);
252 258 fp->f_count++;
253 259 mutex_exit(&fp->f_tlock);
254 260 setf(fd, fp);
261 + if ((filemode & FCLOEXEC) != 0) {
262 + f_setfd(fd, FD_CLOEXEC);
263 + }
255 264 releasef(dupfd);
256 265 }
257 266 return (fd);
258 267 } else {
259 268 setf(fd, NULL);
260 269 unfalloc(fp);
261 270 return (set_errno(error));
262 271 }
263 272 }
264 273 } else {
265 274 error = EINVAL;
266 275 }
267 276 out:
268 277 if (startvp != NULL)
269 278 VN_RELE(startvp);
270 279 return (set_errno(error));
271 280 }
272 281
273 282 #define OPENMODE32(fmode) (((fmode) & (FSEARCH | FEXEC))? \
274 283 (fmode) : (fmode) - FOPEN)
275 284 #define OPENMODE64(fmode) (OPENMODE32(fmode) | FOFFMAX)
276 285 #ifdef _LP64
277 286 #define OPENMODE(fmode) OPENMODE64(fmode)
278 287 #else
279 288 #define OPENMODE(fmode) OPENMODE32(fmode)
280 289 #endif
281 290
282 291 /*
283 292 * Open a file.
284 293 */
285 294 int
286 295 openat(int fd, char *path, int fmode, int cmode)
287 296 {
288 297 return (copen(fd, path, OPENMODE(fmode), cmode));
289 298 }
290 299
291 300 int
292 301 open(char *path, int fmode, int cmode)
293 302 {
294 303 return (openat(AT_FDCWD, path, fmode, cmode));
295 304 }
296 305
297 306 #if defined(_ILP32) || defined(_SYSCALL32_IMPL)
298 307 /*
299 308 * Open for large files in 32-bit environment. Sets the FOFFMAX flag.
300 309 */
301 310 int
302 311 openat64(int fd, char *path, int fmode, int cmode)
303 312 {
304 313 return (copen(fd, path, OPENMODE64(fmode), cmode));
305 314 }
306 315
307 316 int
308 317 open64(char *path, int fmode, int cmode)
309 318 {
310 319 return (openat64(AT_FDCWD, path, fmode, cmode));
311 320 }
312 321
313 322 #endif /* _ILP32 || _SYSCALL32_IMPL */
314 323
315 324 #ifdef _SYSCALL32_IMPL
316 325 /*
317 326 * Open for 32-bit compatibility on 64-bit kernel
318 327 */
319 328 int
320 329 openat32(int fd, char *path, int fmode, int cmode)
321 330 {
322 331 return (copen(fd, path, OPENMODE32(fmode), cmode));
323 332 }
324 333
325 334 int
326 335 open32(char *path, int fmode, int cmode)
327 336 {
328 337 return (openat32(AT_FDCWD, path, fmode, cmode));
329 338 }
330 339
331 340 #endif /* _SYSCALL32_IMPL */
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX