1*8329232eSGordon Ross /*
2*8329232eSGordon Ross  * CDDL HEADER START
3*8329232eSGordon Ross  *
4*8329232eSGordon Ross  * The contents of this file are subject to the terms of the
5*8329232eSGordon Ross  * Common Development and Distribution License (the "License").
6*8329232eSGordon Ross  * You may not use this file except in compliance with the License.
7*8329232eSGordon Ross  *
8*8329232eSGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8329232eSGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*8329232eSGordon Ross  * See the License for the specific language governing permissions
11*8329232eSGordon Ross  * and limitations under the License.
12*8329232eSGordon Ross  *
13*8329232eSGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*8329232eSGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8329232eSGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*8329232eSGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*8329232eSGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8329232eSGordon Ross  *
19*8329232eSGordon Ross  * CDDL HEADER END
20*8329232eSGordon Ross  */
21*8329232eSGordon Ross 
22*8329232eSGordon Ross /*
23*8329232eSGordon Ross  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24*8329232eSGordon Ross  * Copyright 2017, Joyent, Inc.
25*8329232eSGordon Ross  * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
26*8329232eSGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
27*8329232eSGordon Ross  */
28*8329232eSGordon Ross 
29*8329232eSGordon Ross /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
30*8329232eSGordon Ross /*	  All Rights Reserved	*/
31*8329232eSGordon Ross 
32*8329232eSGordon Ross /*
33*8329232eSGordon Ross  * University Copyright- Copyright (c) 1982, 1986, 1988
34*8329232eSGordon Ross  * The Regents of the University of California
35*8329232eSGordon Ross  * All Rights Reserved
36*8329232eSGordon Ross  *
37*8329232eSGordon Ross  * University Acknowledgment- Portions of this document are derived from
38*8329232eSGordon Ross  * software developed by the University of California, Berkeley, and its
39*8329232eSGordon Ross  * contributors.
40*8329232eSGordon Ross  */
41*8329232eSGordon Ross 
42*8329232eSGordon Ross /*
43*8329232eSGordon Ross  * Portions of code from both of:
44*8329232eSGordon Ross  *	syscall/open.c
45*8329232eSGordon Ross  *	fs/vnode.c
46*8329232eSGordon Ross  * heavily modified for this use.
47*8329232eSGordon Ross  */
48*8329232eSGordon Ross 
49*8329232eSGordon Ross #include <sys/types.h>
50*8329232eSGordon Ross #include <sys/param.h>
51*8329232eSGordon Ross #include <sys/t_lock.h>
52*8329232eSGordon Ross #include <sys/errno.h>
53*8329232eSGordon Ross #include <sys/cred.h>
54*8329232eSGordon Ross #include <sys/user.h>
55*8329232eSGordon Ross #include <sys/uio.h>
56*8329232eSGordon Ross #include <sys/file.h>
57*8329232eSGordon Ross #include <sys/pathname.h>
58*8329232eSGordon Ross #include <sys/vfs.h>
59*8329232eSGordon Ross #include <sys/vfs_opreg.h>
60*8329232eSGordon Ross #include <sys/vnode.h>
61*8329232eSGordon Ross #include <sys/rwstlock.h>
62*8329232eSGordon Ross #include <sys/fem.h>
63*8329232eSGordon Ross #include <sys/stat.h>
64*8329232eSGordon Ross #include <sys/mode.h>
65*8329232eSGordon Ross #include <sys/conf.h>
66*8329232eSGordon Ross #include <sys/sysmacros.h>
67*8329232eSGordon Ross #include <sys/cmn_err.h>
68*8329232eSGordon Ross #include <sys/systm.h>
69*8329232eSGordon Ross #include <sys/kmem.h>
70*8329232eSGordon Ross #include <sys/debug.h>
71*8329232eSGordon Ross #include <sys/acl.h>
72*8329232eSGordon Ross #include <sys/nbmlock.h>
73*8329232eSGordon Ross #include <sys/fcntl.h>
74*8329232eSGordon Ross #include <fs/fs_subr.h>
75*8329232eSGordon Ross #include <sys/taskq.h>
76*8329232eSGordon Ross #include <fs/fs_reparse.h>
77*8329232eSGordon Ross #include <sys/time.h>
78*8329232eSGordon Ross 
79*8329232eSGordon Ross #include <libfksmbfs.h>
80*8329232eSGordon Ross 
81*8329232eSGordon Ross /* close and release */
82*8329232eSGordon Ross int
vn_close_rele(vnode_t * vp,int flag)83*8329232eSGordon Ross vn_close_rele(vnode_t *vp, int flag)
84*8329232eSGordon Ross {
85*8329232eSGordon Ross 	int error;
86*8329232eSGordon Ross 
87*8329232eSGordon Ross 	error = VOP_CLOSE(vp, flag, 0, 0, CRED(), NULL);
88*8329232eSGordon Ross 	vn_rele(vp);
89*8329232eSGordon Ross 
90*8329232eSGordon Ross 	return (error);
91*8329232eSGordon Ross }
92*8329232eSGordon Ross 
93*8329232eSGordon Ross /*
94*8329232eSGordon Ross  * Open/create a vnode.
95*8329232eSGordon Ross  * This may be callable by the kernel, the only known use
96*8329232eSGordon Ross  * of user context being that the current user credentials
97*8329232eSGordon Ross  * are used for permissions.  crwhy is defined iff filemode & FCREAT.
98*8329232eSGordon Ross  */
99*8329232eSGordon Ross int
vn_open(char * pnamep,enum uio_seg seg,int filemode,int createmode,struct vnode ** vpp,enum create crwhy,mode_t umask)100*8329232eSGordon Ross vn_open(
101*8329232eSGordon Ross 	char *pnamep,
102*8329232eSGordon Ross 	enum uio_seg seg,
103*8329232eSGordon Ross 	int filemode,
104*8329232eSGordon Ross 	int createmode,
105*8329232eSGordon Ross 	struct vnode **vpp,
106*8329232eSGordon Ross 	enum create crwhy,
107*8329232eSGordon Ross 	mode_t umask)
108*8329232eSGordon Ross {
109*8329232eSGordon Ross 	struct vnode *vp;
110*8329232eSGordon Ross 	int mode;
111*8329232eSGordon Ross 	int accessflags;
112*8329232eSGordon Ross 	int error;
113*8329232eSGordon Ross 	int open_done = 0;
114*8329232eSGordon Ross 	struct vattr vattr;
115*8329232eSGordon Ross 	int estale_retry = 0;
116*8329232eSGordon Ross 
117*8329232eSGordon Ross 	mode = 0;
118*8329232eSGordon Ross 	accessflags = 0;
119*8329232eSGordon Ross 	if (filemode & FREAD)
120*8329232eSGordon Ross 		mode |= VREAD;
121*8329232eSGordon Ross 	if (filemode & (FWRITE|FTRUNC))
122*8329232eSGordon Ross 		mode |= VWRITE;
123*8329232eSGordon Ross 	if (filemode & (FSEARCH|FEXEC|FXATTRDIROPEN))
124*8329232eSGordon Ross 		mode |= VEXEC;
125*8329232eSGordon Ross 
126*8329232eSGordon Ross 	if (filemode & FAPPEND)
127*8329232eSGordon Ross 		accessflags |= V_APPEND;
128*8329232eSGordon Ross 
129*8329232eSGordon Ross top:
130*8329232eSGordon Ross 	if (filemode & FCREAT) {
131*8329232eSGordon Ross 		enum vcexcl excl;
132*8329232eSGordon Ross 
133*8329232eSGordon Ross 		/*
134*8329232eSGordon Ross 		 * Wish to create a file.
135*8329232eSGordon Ross 		 */
136*8329232eSGordon Ross 		vattr.va_type = VREG;
137*8329232eSGordon Ross 		vattr.va_mode = createmode;
138*8329232eSGordon Ross 		vattr.va_mask = AT_TYPE|AT_MODE;
139*8329232eSGordon Ross 		if (filemode & FTRUNC) {
140*8329232eSGordon Ross 			vattr.va_size = 0;
141*8329232eSGordon Ross 			vattr.va_mask |= AT_SIZE;
142*8329232eSGordon Ross 		}
143*8329232eSGordon Ross 		if (filemode & FEXCL)
144*8329232eSGordon Ross 			excl = EXCL;
145*8329232eSGordon Ross 		else
146*8329232eSGordon Ross 			excl = NONEXCL;
147*8329232eSGordon Ross 
148*8329232eSGordon Ross 		if ((error =
149*8329232eSGordon Ross 		    vn_create(pnamep, seg, &vattr, excl, mode, &vp, crwhy,
150*8329232eSGordon Ross 		    (filemode & ~(FTRUNC|FEXCL)), umask)) != 0)
151*8329232eSGordon Ross 			return (error);
152*8329232eSGordon Ross 	} else {
153*8329232eSGordon Ross 		/*
154*8329232eSGordon Ross 		 * Wish to open a file.  Just look it up.
155*8329232eSGordon Ross 		 * Was lookupnameat()
156*8329232eSGordon Ross 		 */
157*8329232eSGordon Ross 		if ((error = fake_lookup(NULL, pnamep, &vp)) != 0) {
158*8329232eSGordon Ross 			if ((error == ESTALE) &&
159*8329232eSGordon Ross 			    fs_need_estale_retry(estale_retry++))
160*8329232eSGordon Ross 				goto top;
161*8329232eSGordon Ross 			return (error);
162*8329232eSGordon Ross 		}
163*8329232eSGordon Ross 
164*8329232eSGordon Ross 		/*
165*8329232eSGordon Ross 		 * Want the XATTRDIR under it?
166*8329232eSGordon Ross 		 */
167*8329232eSGordon Ross 		if (filemode & FXATTRDIROPEN) {
168*8329232eSGordon Ross 			vnode_t *xvp = NULL;
169*8329232eSGordon Ross 			error = VOP_LOOKUP(vp, NULL, &xvp, NULL,
170*8329232eSGordon Ross 			    LOOKUP_XATTR, rootdir, CRED(), NULL,
171*8329232eSGordon Ross 			    NULL, NULL);
172*8329232eSGordon Ross 			VN_RELE(vp);
173*8329232eSGordon Ross 			vp = xvp;
174*8329232eSGordon Ross 			/* continue with vp */
175*8329232eSGordon Ross 		}
176*8329232eSGordon Ross 
177*8329232eSGordon Ross 		/*
178*8329232eSGordon Ross 		 * Can't write directories, active texts, or
179*8329232eSGordon Ross 		 * read-only filesystems.  Can't truncate files
180*8329232eSGordon Ross 		 * on which mandatory locking is in effect.
181*8329232eSGordon Ross 		 */
182*8329232eSGordon Ross 		if (filemode & (FWRITE|FTRUNC)) {
183*8329232eSGordon Ross 			if (vp->v_type == VDIR) {
184*8329232eSGordon Ross 				error = EISDIR;
185*8329232eSGordon Ross 				goto out;
186*8329232eSGordon Ross 			}
187*8329232eSGordon Ross 		}
188*8329232eSGordon Ross 		/*
189*8329232eSGordon Ross 		 * Check permissions.
190*8329232eSGordon Ross 		 */
191*8329232eSGordon Ross 		if (error = VOP_ACCESS(vp, mode, accessflags, CRED(), NULL))
192*8329232eSGordon Ross 			goto out;
193*8329232eSGordon Ross 		/*
194*8329232eSGordon Ross 		 * Require FSEARCH to return a directory.
195*8329232eSGordon Ross 		 * Require FEXEC to return a regular file.
196*8329232eSGordon Ross 		 */
197*8329232eSGordon Ross 		if ((filemode & FSEARCH) && vp->v_type != VDIR) {
198*8329232eSGordon Ross 			error = ENOTDIR;
199*8329232eSGordon Ross 			goto out;
200*8329232eSGordon Ross 		}
201*8329232eSGordon Ross 		if ((filemode & FEXEC) && vp->v_type != VREG) {
202*8329232eSGordon Ross 			error = ENOEXEC;
203*8329232eSGordon Ross 			goto out;
204*8329232eSGordon Ross 		}
205*8329232eSGordon Ross 	}
206*8329232eSGordon Ross 
207*8329232eSGordon Ross 	/*
208*8329232eSGordon Ross 	 * Do remaining checks for FNOFOLLOW and FNOLINKS.
209*8329232eSGordon Ross 	 */
210*8329232eSGordon Ross 	if ((filemode & FNOFOLLOW) && vp->v_type == VLNK) {
211*8329232eSGordon Ross 		error = ELOOP;
212*8329232eSGordon Ross 		goto out;
213*8329232eSGordon Ross 	}
214*8329232eSGordon Ross 	if (filemode & FNOLINKS) {
215*8329232eSGordon Ross 		vattr.va_mask = AT_NLINK;
216*8329232eSGordon Ross 		if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))) {
217*8329232eSGordon Ross 			goto out;
218*8329232eSGordon Ross 		}
219*8329232eSGordon Ross 		if (vattr.va_nlink != 1) {
220*8329232eSGordon Ross 			error = EMLINK;
221*8329232eSGordon Ross 			goto out;
222*8329232eSGordon Ross 		}
223*8329232eSGordon Ross 	}
224*8329232eSGordon Ross 
225*8329232eSGordon Ross 	/*
226*8329232eSGordon Ross 	 * Opening a socket corresponding to the AF_UNIX pathname
227*8329232eSGordon Ross 	 * in the filesystem name space is not supported...
228*8329232eSGordon Ross 	 */
229*8329232eSGordon Ross 	if (vp->v_type == VSOCK) {
230*8329232eSGordon Ross 		error = EOPNOTSUPP;
231*8329232eSGordon Ross 		goto out;
232*8329232eSGordon Ross 	}
233*8329232eSGordon Ross 
234*8329232eSGordon Ross 	/*
235*8329232eSGordon Ross 	 * Do opening protocol.
236*8329232eSGordon Ross 	 */
237*8329232eSGordon Ross 	error = VOP_OPEN(&vp, filemode, CRED(), NULL);
238*8329232eSGordon Ross 	if (error)
239*8329232eSGordon Ross 		goto out;
240*8329232eSGordon Ross 	open_done = 1;
241*8329232eSGordon Ross 
242*8329232eSGordon Ross 	/*
243*8329232eSGordon Ross 	 * Truncate if required.
244*8329232eSGordon Ross 	 */
245*8329232eSGordon Ross 	if ((filemode & FTRUNC) && !(filemode & FCREAT)) {
246*8329232eSGordon Ross 		vattr.va_size = 0;
247*8329232eSGordon Ross 		vattr.va_mask = AT_SIZE;
248*8329232eSGordon Ross 		if ((error = VOP_SETATTR(vp, &vattr, 0, CRED(), NULL)) != 0)
249*8329232eSGordon Ross 			goto out;
250*8329232eSGordon Ross 	}
251*8329232eSGordon Ross out:
252*8329232eSGordon Ross 	ASSERT(vp->v_count > 0);
253*8329232eSGordon Ross 
254*8329232eSGordon Ross 	if (error) {
255*8329232eSGordon Ross 		if (open_done) {
256*8329232eSGordon Ross 			(void) VOP_CLOSE(vp, filemode, 1, (offset_t)0, CRED(),
257*8329232eSGordon Ross 			    NULL);
258*8329232eSGordon Ross 			open_done = 0;
259*8329232eSGordon Ross 		}
260*8329232eSGordon Ross 		VN_RELE(vp);
261*8329232eSGordon Ross 	} else
262*8329232eSGordon Ross 		*vpp = vp;
263*8329232eSGordon Ross 	return (error);
264*8329232eSGordon Ross }
265*8329232eSGordon Ross 
266*8329232eSGordon Ross 
267*8329232eSGordon Ross /*
268*8329232eSGordon Ross  * Create a vnode (makenode).
269*8329232eSGordon Ross  */
270*8329232eSGordon Ross int
vn_create(char * pnamep,enum uio_seg seg,struct vattr * vap,enum vcexcl excl,int mode,struct vnode ** vpp,enum create why,int flag,mode_t umask)271*8329232eSGordon Ross vn_create(
272*8329232eSGordon Ross 	char *pnamep,
273*8329232eSGordon Ross 	enum uio_seg seg,
274*8329232eSGordon Ross 	struct vattr *vap,
275*8329232eSGordon Ross 	enum vcexcl excl,
276*8329232eSGordon Ross 	int mode,
277*8329232eSGordon Ross 	struct vnode **vpp,
278*8329232eSGordon Ross 	enum create why,
279*8329232eSGordon Ross 	int flag,
280*8329232eSGordon Ross 	mode_t umask)
281*8329232eSGordon Ross {
282*8329232eSGordon Ross 	struct vnode *dvp = NULL;	/* ptr to parent dir vnode */
283*8329232eSGordon Ross 	char *lastcomp = NULL;
284*8329232eSGordon Ross 	int error;
285*8329232eSGordon Ross 
286*8329232eSGordon Ross 	ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
287*8329232eSGordon Ross 
288*8329232eSGordon Ross 	flag &= ~(FNOFOLLOW|FNOLINKS);
289*8329232eSGordon Ross 
290*8329232eSGordon Ross 	*vpp = NULL;
291*8329232eSGordon Ross 
292*8329232eSGordon Ross 	/*
293*8329232eSGordon Ross 	 * Lookup directory and last component
294*8329232eSGordon Ross 	 */
295*8329232eSGordon Ross 	error = fake_lookup_dir(pnamep, &dvp, &lastcomp);
296*8329232eSGordon Ross 	if (error != 0) {
297*8329232eSGordon Ross 		/* dir not found */
298*8329232eSGordon Ross 		return (error);
299*8329232eSGordon Ross 	}
300*8329232eSGordon Ross 
301*8329232eSGordon Ross 	/*
302*8329232eSGordon Ross 	 * If default ACLs are defined for the directory don't apply the
303*8329232eSGordon Ross 	 * umask if umask is passed.
304*8329232eSGordon Ross 	 */
305*8329232eSGordon Ross 
306*8329232eSGordon Ross 	if (umask) {
307*8329232eSGordon Ross 		/*
308*8329232eSGordon Ross 		 * Apply the umask if no default ACLs...
309*8329232eSGordon Ross 		 */
310*8329232eSGordon Ross 		vap->va_mode &= ~umask;
311*8329232eSGordon Ross 	}
312*8329232eSGordon Ross 
313*8329232eSGordon Ross 	if (dvp->v_vfsp->vfs_flag & VFS_RDONLY) {
314*8329232eSGordon Ross 		error = EROFS;
315*8329232eSGordon Ross 		goto out;
316*8329232eSGordon Ross 	}
317*8329232eSGordon Ross 
318*8329232eSGordon Ross 	/*
319*8329232eSGordon Ross 	 * Call mkdir() if specified, otherwise create().
320*8329232eSGordon Ross 	 */
321*8329232eSGordon Ross 	if (why == CRMKDIR) {
322*8329232eSGordon Ross 		/*
323*8329232eSGordon Ross 		 * N.B., if vn_createat() ever requests
324*8329232eSGordon Ross 		 * case-insensitive behavior then it will need
325*8329232eSGordon Ross 		 * to be passed to VOP_MKDIR().  VOP_CREATE()
326*8329232eSGordon Ross 		 * will already get it via "flag"
327*8329232eSGordon Ross 		 */
328*8329232eSGordon Ross 		error = VOP_MKDIR(dvp, lastcomp, vap, vpp, CRED(),
329*8329232eSGordon Ross 		    NULL, 0, NULL);
330*8329232eSGordon Ross 	} else {
331*8329232eSGordon Ross 		error = VOP_CREATE(dvp, lastcomp, vap,
332*8329232eSGordon Ross 		    excl, mode, vpp, CRED(), flag, NULL, NULL);
333*8329232eSGordon Ross 	}
334*8329232eSGordon Ross 
335*8329232eSGordon Ross out:
336*8329232eSGordon Ross 	if (dvp != NULL)
337*8329232eSGordon Ross 		VN_RELE(dvp);
338*8329232eSGordon Ross 
339*8329232eSGordon Ross 	return (error);
340*8329232eSGordon Ross }
341