1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A
1N/A/*
1N/A * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
1N/A */
1N/A
1N/A/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
1N/A/* All Rights Reserved */
1N/A
1N/A/*
1N/A * Portions of this source code were derived from Berkeley 4.3 BSD
1N/A * under license from the Regents of the University of California.
1N/A */
1N/A
1N/A#include <sys/param.h>
1N/A#include <sys/isa_defs.h>
1N/A#include <sys/types.h>
1N/A#include <sys/sysmacros.h>
1N/A#include <sys/cred_impl.h>
1N/A#include <sys/systm.h>
1N/A#include <sys/errno.h>
1N/A#include <sys/pathname.h>
1N/A#include <sys/vnode.h>
1N/A#include <sys/uio.h>
1N/A#include <sys/cmn_err.h>
1N/A#include <sys/debug.h>
1N/A#include <sys/file.h>
1N/A#include <fs/fs_subr.h>
1N/A#include <c2/audit.h>
1N/A#include <sys/fcntl.h>
1N/A
1N/A/*
1N/A * Determine accessibility of file.
1N/A */
1N/A
1N/A#define E_OK 010 /* use effective ids */
1N/A#define R_OK 004
1N/A#define W_OK 002
1N/A#define X_OK 001
1N/A
1N/Astatic int
1N/Acaccess(char *fname, int fmode, vnode_t *startvp)
1N/A{
1N/A vnode_t *vp;
1N/A cred_t *tmpcr;
1N/A int error;
1N/A int mode;
1N/A int eok;
1N/A cred_t *cr;
1N/A int estale_retry = 0;
1N/A
1N/A if (fmode & ~(E_OK|R_OK|W_OK|X_OK))
1N/A return (EINVAL);
1N/A
1N/A mode = ((fmode & (R_OK|W_OK|X_OK)) << 6);
1N/A
1N/A cr = CRED();
1N/A
1N/A /* OK to use effective uid/gid, i.e., no need to crdup(CRED())? */
1N/A eok = (fmode & E_OK) ||
1N/A (cr->cr_uid == cr->cr_ruid && cr->cr_gid == cr->cr_rgid);
1N/A
1N/A if (eok)
1N/A tmpcr = cr;
1N/A else {
1N/A tmpcr = crdup(cr);
1N/A tmpcr->cr_uid = cr->cr_ruid;
1N/A tmpcr->cr_gid = cr->cr_rgid;
1N/A tmpcr->cr_ruid = cr->cr_uid;
1N/A tmpcr->cr_rgid = cr->cr_gid;
1N/A }
1N/A
1N/Alookup:
1N/A if (error = lookupnameatcred(fname, UIO_USERSPACE, FOLLOW, NULLVPP, &vp,
1N/A startvp, tmpcr)) {
1N/A if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
1N/A goto lookup;
1N/A if (!eok)
1N/A crfree(tmpcr);
1N/A return (error);
1N/A }
1N/A
1N/A if (mode) {
1N/A error = VOP_ACCESS(vp, mode, 0, tmpcr, NULL);
1N/A if (error) {
1N/A if ((error == ESTALE) &&
1N/A fs_need_estale_retry(estale_retry++)) {
1N/A VN_RELE(vp);
1N/A goto lookup;
1N/A }
1N/A }
1N/A }
1N/A
1N/A if (!eok)
1N/A crfree(tmpcr);
1N/A VN_RELE(vp);
1N/A return (error);
1N/A}
1N/A
1N/Aint
1N/Afaccessat(int fd, char *fname, int fmode, int flag)
1N/A{
1N/A vnode_t *startvp;
1N/A int error;
1N/A
1N/A if ((flag & ~AT_EACCESS) != 0)
1N/A return (set_errno(EINVAL));
1N/A
1N/A if (fname == NULL)
1N/A return (set_errno(EFAULT));
1N/A if ((error = fgetstartvp(fd, fname, &startvp)) != 0)
1N/A return (set_errno(error));
1N/A if (AU_AUDITING() && startvp != NULL)
1N/A audit_setfsat_path(1);
1N/A
1N/A /* Do not allow E_OK unless AT_EACCESS flag is set */
1N/A fmode &= ~E_OK;
1N/A if (flag & AT_EACCESS)
1N/A fmode |= E_OK;
1N/A
1N/A error = caccess(fname, fmode, startvp);
1N/A if (startvp != NULL)
1N/A VN_RELE(startvp);
1N/A if (error)
1N/A return (set_errno(error));
return (0);
}
int
access(char *fname, int fmode)
{
return (faccessat(AT_FDCWD, fname, fmode, 0));
}