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