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