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