xref: /titanic_50/usr/src/uts/common/syscall/open.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/mode.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
52*7c478bd9Sstevel@tonic-gate #include <c2/audit.h>
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * Common code for open()/openat() and creat().  Check permissions, allocate
56*7c478bd9Sstevel@tonic-gate  * an open file structure, and call the device open routine (if any).
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static int
60*7c478bd9Sstevel@tonic-gate copen(int startfd, char *fname, int filemode, int createmode)
61*7c478bd9Sstevel@tonic-gate {
62*7c478bd9Sstevel@tonic-gate 	struct pathname pn;
63*7c478bd9Sstevel@tonic-gate 	vnode_t *vp, *sdvp;
64*7c478bd9Sstevel@tonic-gate 	file_t *fp, *startfp;
65*7c478bd9Sstevel@tonic-gate 	enum vtype type;
66*7c478bd9Sstevel@tonic-gate 	int error;
67*7c478bd9Sstevel@tonic-gate 	int fd, dupfd;
68*7c478bd9Sstevel@tonic-gate 	vnode_t *startvp;
69*7c478bd9Sstevel@tonic-gate 	proc_t *p = curproc;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	if (startfd == AT_FDCWD) {
72*7c478bd9Sstevel@tonic-gate 		/*
73*7c478bd9Sstevel@tonic-gate 		 * Regular open()
74*7c478bd9Sstevel@tonic-gate 		 */
75*7c478bd9Sstevel@tonic-gate 		startvp = NULL;
76*7c478bd9Sstevel@tonic-gate 	} else {
77*7c478bd9Sstevel@tonic-gate 		/*
78*7c478bd9Sstevel@tonic-gate 		 * We're here via openat()
79*7c478bd9Sstevel@tonic-gate 		 */
80*7c478bd9Sstevel@tonic-gate 		char startchar;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 		if (copyin(fname, &startchar, sizeof (char)))
83*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 		/*
86*7c478bd9Sstevel@tonic-gate 		 * if startchar is / then startfd is ignored
87*7c478bd9Sstevel@tonic-gate 		 */
88*7c478bd9Sstevel@tonic-gate 		if (startchar == '/')
89*7c478bd9Sstevel@tonic-gate 			startvp = NULL;
90*7c478bd9Sstevel@tonic-gate 		else {
91*7c478bd9Sstevel@tonic-gate 			if ((startfp = getf(startfd)) == NULL)
92*7c478bd9Sstevel@tonic-gate 				return (set_errno(EBADF));
93*7c478bd9Sstevel@tonic-gate 			startvp = startfp->f_vnode;
94*7c478bd9Sstevel@tonic-gate 			VN_HOLD(startvp);
95*7c478bd9Sstevel@tonic-gate 			releasef(startfd);
96*7c478bd9Sstevel@tonic-gate 		}
97*7c478bd9Sstevel@tonic-gate 	}
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	if (filemode & FXATTR) {
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 		/*
102*7c478bd9Sstevel@tonic-gate 		 * Make sure we have a valid request.
103*7c478bd9Sstevel@tonic-gate 		 * We must either have a real fd or AT_FDCWD
104*7c478bd9Sstevel@tonic-gate 		 */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 		if (startfd != AT_FDCWD && startvp == NULL) {
107*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
108*7c478bd9Sstevel@tonic-gate 			goto out;
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 		if (error = pn_get(fname, UIO_USERSPACE, &pn)) {
112*7c478bd9Sstevel@tonic-gate 			goto out;
113*7c478bd9Sstevel@tonic-gate 		}
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 		if (startfd == AT_FDCWD) {
116*7c478bd9Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
117*7c478bd9Sstevel@tonic-gate 			startvp = PTOU(p)->u_cdir;
118*7c478bd9Sstevel@tonic-gate 			VN_HOLD(startvp);
119*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
120*7c478bd9Sstevel@tonic-gate 		}
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 		/*
123*7c478bd9Sstevel@tonic-gate 		 * Verify permission to put attributes on file
124*7c478bd9Sstevel@tonic-gate 		 */
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 		if ((VOP_ACCESS(startvp, VREAD, 0, CRED()) != 0) &&
127*7c478bd9Sstevel@tonic-gate 		    (VOP_ACCESS(startvp, VWRITE, 0, CRED()) != 0) &&
128*7c478bd9Sstevel@tonic-gate 		    (VOP_ACCESS(startvp, VEXEC, 0, CRED()) != 0)) {
129*7c478bd9Sstevel@tonic-gate 			error = EACCES;
130*7c478bd9Sstevel@tonic-gate 			pn_free(&pn);
131*7c478bd9Sstevel@tonic-gate 			goto out;
132*7c478bd9Sstevel@tonic-gate 		}
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 		if ((startvp->v_vfsp->vfs_flag & VFS_XATTR) != 0) {
135*7c478bd9Sstevel@tonic-gate 			error = VOP_LOOKUP(startvp, "", &sdvp, &pn,
136*7c478bd9Sstevel@tonic-gate 			    LOOKUP_XATTR|CREATE_XATTR_DIR, rootvp, CRED());
137*7c478bd9Sstevel@tonic-gate 		} else {
138*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
139*7c478bd9Sstevel@tonic-gate 		}
140*7c478bd9Sstevel@tonic-gate 		pn_free(&pn);
141*7c478bd9Sstevel@tonic-gate 		if (error != 0)
142*7c478bd9Sstevel@tonic-gate 			goto out;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 		VN_RELE(startvp);
145*7c478bd9Sstevel@tonic-gate 		startvp = sdvp;
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if ((filemode & (FREAD|FWRITE)) != 0) {
149*7c478bd9Sstevel@tonic-gate 		if ((filemode & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY))
150*7c478bd9Sstevel@tonic-gate 			filemode &= ~FNDELAY;
151*7c478bd9Sstevel@tonic-gate 		error = falloc((vnode_t *)NULL, filemode, &fp, &fd);
152*7c478bd9Sstevel@tonic-gate 		if (error == 0) {
153*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
154*7c478bd9Sstevel@tonic-gate 			if (audit_active)
155*7c478bd9Sstevel@tonic-gate 				audit_setfsat_path(1);
156*7c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */
157*7c478bd9Sstevel@tonic-gate 			/*
158*7c478bd9Sstevel@tonic-gate 			 * Last arg is a don't-care term if
159*7c478bd9Sstevel@tonic-gate 			 * !(filemode & FCREAT).
160*7c478bd9Sstevel@tonic-gate 			 */
161*7c478bd9Sstevel@tonic-gate 			error = vn_openat(fname, UIO_USERSPACE, filemode,
162*7c478bd9Sstevel@tonic-gate 			    (int)(createmode & MODEMASK), &vp, CRCREAT,
163*7c478bd9Sstevel@tonic-gate 			    u.u_cmask, startvp);
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 			if (startvp != NULL)
166*7c478bd9Sstevel@tonic-gate 				VN_RELE(startvp);
167*7c478bd9Sstevel@tonic-gate 			if (error == 0) {
168*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
169*7c478bd9Sstevel@tonic-gate 				if (audit_active)
170*7c478bd9Sstevel@tonic-gate 					audit_copen(fd, fp, vp);
171*7c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */
172*7c478bd9Sstevel@tonic-gate 				if ((vp->v_flag & VDUP) == 0) {
173*7c478bd9Sstevel@tonic-gate 					fp->f_vnode = vp;
174*7c478bd9Sstevel@tonic-gate 					mutex_exit(&fp->f_tlock);
175*7c478bd9Sstevel@tonic-gate 					/*
176*7c478bd9Sstevel@tonic-gate 					 * We must now fill in the slot
177*7c478bd9Sstevel@tonic-gate 					 * falloc reserved.
178*7c478bd9Sstevel@tonic-gate 					 */
179*7c478bd9Sstevel@tonic-gate 					setf(fd, fp);
180*7c478bd9Sstevel@tonic-gate 					return (fd);
181*7c478bd9Sstevel@tonic-gate 				} else {
182*7c478bd9Sstevel@tonic-gate 					/*
183*7c478bd9Sstevel@tonic-gate 					 * Special handling for /dev/fd.
184*7c478bd9Sstevel@tonic-gate 					 * Give up the file pointer
185*7c478bd9Sstevel@tonic-gate 					 * and dup the indicated file descriptor
186*7c478bd9Sstevel@tonic-gate 					 * (in v_rdev). This is ugly, but I've
187*7c478bd9Sstevel@tonic-gate 					 * seen worse.
188*7c478bd9Sstevel@tonic-gate 					 */
189*7c478bd9Sstevel@tonic-gate 					unfalloc(fp);
190*7c478bd9Sstevel@tonic-gate 					dupfd = getminor(vp->v_rdev);
191*7c478bd9Sstevel@tonic-gate 					type = vp->v_type;
192*7c478bd9Sstevel@tonic-gate 					mutex_enter(&vp->v_lock);
193*7c478bd9Sstevel@tonic-gate 					vp->v_flag &= ~VDUP;
194*7c478bd9Sstevel@tonic-gate 					mutex_exit(&vp->v_lock);
195*7c478bd9Sstevel@tonic-gate 					VN_RELE(vp);
196*7c478bd9Sstevel@tonic-gate 					if (type != VCHR)
197*7c478bd9Sstevel@tonic-gate 						return (set_errno(EINVAL));
198*7c478bd9Sstevel@tonic-gate 					if ((fp = getf(dupfd)) == NULL) {
199*7c478bd9Sstevel@tonic-gate 						setf(fd, NULL);
200*7c478bd9Sstevel@tonic-gate 						return (set_errno(EBADF));
201*7c478bd9Sstevel@tonic-gate 					}
202*7c478bd9Sstevel@tonic-gate 					mutex_enter(&fp->f_tlock);
203*7c478bd9Sstevel@tonic-gate 					fp->f_count++;
204*7c478bd9Sstevel@tonic-gate 					mutex_exit(&fp->f_tlock);
205*7c478bd9Sstevel@tonic-gate 					setf(fd, fp);
206*7c478bd9Sstevel@tonic-gate 					releasef(dupfd);
207*7c478bd9Sstevel@tonic-gate 				}
208*7c478bd9Sstevel@tonic-gate 				return (fd);
209*7c478bd9Sstevel@tonic-gate 			} else {
210*7c478bd9Sstevel@tonic-gate 				setf(fd, NULL);
211*7c478bd9Sstevel@tonic-gate 				unfalloc(fp);
212*7c478bd9Sstevel@tonic-gate 				return (set_errno(error));
213*7c478bd9Sstevel@tonic-gate 			}
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 	} else {
216*7c478bd9Sstevel@tonic-gate 		error = EINVAL;
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate out:
219*7c478bd9Sstevel@tonic-gate 	if (startvp != NULL)
220*7c478bd9Sstevel@tonic-gate 		VN_RELE(startvp);
221*7c478bd9Sstevel@tonic-gate 	return (set_errno(error));
222*7c478bd9Sstevel@tonic-gate }
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate #define	OPENMODE32(fmode)	((int)((fmode)-FOPEN))
225*7c478bd9Sstevel@tonic-gate #define	CREATMODE32		(FWRITE|FCREAT|FTRUNC)
226*7c478bd9Sstevel@tonic-gate #define	OPENMODE64(fmode)	(OPENMODE32(fmode) | FOFFMAX)
227*7c478bd9Sstevel@tonic-gate #define	CREATMODE64		(CREATMODE32 | FOFFMAX)
228*7c478bd9Sstevel@tonic-gate #ifdef _LP64
229*7c478bd9Sstevel@tonic-gate #define	OPENMODE(fmode)		OPENMODE64(fmode)
230*7c478bd9Sstevel@tonic-gate #define	CREATMODE		CREATMODE64
231*7c478bd9Sstevel@tonic-gate #else
232*7c478bd9Sstevel@tonic-gate #define	OPENMODE		OPENMODE32
233*7c478bd9Sstevel@tonic-gate #define	CREATMODE		CREATMODE32
234*7c478bd9Sstevel@tonic-gate #endif
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate /*
237*7c478bd9Sstevel@tonic-gate  * Open a file.
238*7c478bd9Sstevel@tonic-gate  */
239*7c478bd9Sstevel@tonic-gate int
240*7c478bd9Sstevel@tonic-gate open(char *fname, int fmode, int cmode)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, OPENMODE(fmode), cmode));
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate /*
246*7c478bd9Sstevel@tonic-gate  * Create a file.
247*7c478bd9Sstevel@tonic-gate  */
248*7c478bd9Sstevel@tonic-gate int
249*7c478bd9Sstevel@tonic-gate creat(char *fname, int cmode)
250*7c478bd9Sstevel@tonic-gate {
251*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, CREATMODE, cmode));
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate int
255*7c478bd9Sstevel@tonic-gate openat(int fd, char *path, int fmode, int cmode)
256*7c478bd9Sstevel@tonic-gate {
257*7c478bd9Sstevel@tonic-gate 	return (copen(fd, path, OPENMODE(fmode), cmode));
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate #if defined(_ILP32) || defined(_SYSCALL32_IMPL)
261*7c478bd9Sstevel@tonic-gate /*
262*7c478bd9Sstevel@tonic-gate  * Open and Creat for large files in 32-bit environment. Sets the FOFFMAX flag.
263*7c478bd9Sstevel@tonic-gate  */
264*7c478bd9Sstevel@tonic-gate int
265*7c478bd9Sstevel@tonic-gate open64(char *fname, int fmode, int cmode)
266*7c478bd9Sstevel@tonic-gate {
267*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, OPENMODE64(fmode), cmode));
268*7c478bd9Sstevel@tonic-gate }
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate int
271*7c478bd9Sstevel@tonic-gate creat64(char *fname, int cmode)
272*7c478bd9Sstevel@tonic-gate {
273*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, CREATMODE64, cmode));
274*7c478bd9Sstevel@tonic-gate }
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate int
277*7c478bd9Sstevel@tonic-gate openat64(int fd, char *path, int fmode, int cmode)
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	return (copen(fd, path, OPENMODE64(fmode), cmode));
280*7c478bd9Sstevel@tonic-gate }
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate #endif	/* _ILP32 || _SYSCALL32_IMPL */
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
285*7c478bd9Sstevel@tonic-gate /*
286*7c478bd9Sstevel@tonic-gate  * Open and Creat for 32-bit compatibility on 64-bit kernel
287*7c478bd9Sstevel@tonic-gate  */
288*7c478bd9Sstevel@tonic-gate int
289*7c478bd9Sstevel@tonic-gate open32(char *fname, int fmode, int cmode)
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, OPENMODE32(fmode), cmode));
292*7c478bd9Sstevel@tonic-gate }
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate int
295*7c478bd9Sstevel@tonic-gate creat32(char *fname, int cmode)
296*7c478bd9Sstevel@tonic-gate {
297*7c478bd9Sstevel@tonic-gate 	return (copen(AT_FDCWD, fname, CREATMODE32, cmode));
298*7c478bd9Sstevel@tonic-gate }
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate int
301*7c478bd9Sstevel@tonic-gate openat32(int fd, char *path, int fmode, int cmode)
302*7c478bd9Sstevel@tonic-gate {
303*7c478bd9Sstevel@tonic-gate 	return (copen(fd, path, OPENMODE32(fmode), cmode));
304*7c478bd9Sstevel@tonic-gate }
305*7c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32_IMPL */
306