123398Smckusick /* 229116Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323398Smckusick * All rights reserved. The Berkeley software License Agreement 423398Smckusick * specifies the terms and conditions for redistribution. 523398Smckusick * 6*37552Smckusick * @(#)vfs_vnops.c 7.3 (Berkeley) 04/26/89 723398Smckusick */ 818Sbill 917099Sbloom #include "param.h" 1017099Sbloom #include "systm.h" 1117099Sbloom #include "dir.h" 1217099Sbloom #include "user.h" 1317099Sbloom #include "fs.h" 1417099Sbloom #include "file.h" 1517099Sbloom #include "conf.h" 1617099Sbloom #include "inode.h" 1717099Sbloom #include "acct.h" 1817099Sbloom #include "mount.h" 1917099Sbloom #include "socket.h" 2017099Sbloom #include "socketvar.h" 2117099Sbloom #include "proc.h" 2218Sbill 2337520Smckusick #include "machine/reg.h" 2437520Smckusick 2518Sbill /* 2618Sbill * Check mode permission on inode pointer. 2718Sbill * Mode is READ, WRITE or EXEC. 2818Sbill * In the case of WRITE, the 2918Sbill * read-only status of the file 3018Sbill * system is checked. 3118Sbill * Also in WRITE, prototype text 3218Sbill * segments cannot be written. 3318Sbill * The mode is shifted to select 3418Sbill * the owner/group/other fields. 3518Sbill * The super user is granted all 3618Sbill * permissions. 3718Sbill */ 3818Sbill access(ip, mode) 394817Swnj register struct inode *ip; 404817Swnj int mode; 4118Sbill { 4218Sbill register m; 4318362Skarels register gid_t *gp; 4418Sbill 4518Sbill m = mode; 464817Swnj if (m == IWRITE) { 4711162Ssam /* 4811162Ssam * Disallow write attempts on read-only 4911162Ssam * file systems; unless the file is a block 5011162Ssam * or character device resident on the 5111162Ssam * file system. 5211162Ssam */ 536569Smckusic if (ip->i_fs->fs_ronly != 0) { 548956Sroot if ((ip->i_mode & IFMT) != IFCHR && 558956Sroot (ip->i_mode & IFMT) != IFBLK) { 568956Sroot u.u_error = EROFS; 578956Sroot return (1); 588956Sroot } 5918Sbill } 6011162Ssam /* 6111162Ssam * If there's shared text associated with 6211162Ssam * the inode, try to free it up once. If 6311162Ssam * we fail, we can't allow writing. 6411162Ssam */ 6511162Ssam if (ip->i_flag&ITEXT) 6618Sbill xrele(ip); 674817Swnj if (ip->i_flag & ITEXT) { 6818Sbill u.u_error = ETXTBSY; 694817Swnj return (1); 7018Sbill } 7118Sbill } 7211162Ssam /* 7311162Ssam * If you're the super-user, 7411162Ssam * you always get access. 7511162Ssam */ 764817Swnj if (u.u_uid == 0) 774817Swnj return (0); 7811162Ssam /* 7911162Ssam * Access check is based on only 8011162Ssam * one of owner, group, public. 8111162Ssam * If not owner, then check group. 8211162Ssam * If not a member of the group, then 8311162Ssam * check public access. 8411162Ssam */ 854817Swnj if (u.u_uid != ip->i_uid) { 8618Sbill m >>= 3; 8711162Ssam if (u.u_gid == ip->i_gid) 8811162Ssam goto found; 8911812Ssam gp = u.u_groups; 9011812Ssam for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) 9110044Ssam if (ip->i_gid == *gp) 927867Sroot goto found; 937867Sroot m >>= 3; 947867Sroot found: 957867Sroot ; 9618Sbill } 974817Swnj if ((ip->i_mode&m) != 0) 984817Swnj return (0); 9918Sbill u.u_error = EACCES; 1004817Swnj return (1); 10118Sbill } 10218Sbill 10318Sbill /* 10418Sbill * Look up a pathname and test if 10518Sbill * the resultant inode is owned by the 10618Sbill * current user. 10718Sbill * If not, try for super-user. 10818Sbill * If permission is granted, 10918Sbill * return inode pointer. 11018Sbill */ 11118Sbill struct inode * 11216693Smckusick owner(fname, follow) 11316693Smckusick caddr_t fname; 1145990Swnj int follow; 11518Sbill { 11618Sbill register struct inode *ip; 11716693Smckusick register struct nameidata *ndp = &u.u_nd; 11818Sbill 11916693Smckusick ndp->ni_nameiop = LOOKUP | follow; 12016693Smckusick ndp->ni_segflg = UIO_USERSPACE; 12116693Smckusick ndp->ni_dirp = fname; 12216693Smckusick ip = namei(ndp); 1234817Swnj if (ip == NULL) 1244817Swnj return (NULL); 1254817Swnj if (u.u_uid == ip->i_uid) 1264817Swnj return (ip); 127*37552Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) { 128*37552Smckusick iput(ip); 129*37552Smckusick return (NULL); 130*37552Smckusick } 131*37552Smckusick return (ip); 13218Sbill } 13318Sbill 13418Sbill /* 135*37552Smckusick * Test if the current user is the super user. 13618Sbill */ 137*37552Smckusick suser(uid, acflag) 138*37552Smckusick uid_t uid; 139*37552Smckusick short *acflag; 14018Sbill { 14118Sbill 142*37552Smckusick if (uid == 0) { 143*37552Smckusick if (acflag) 144*37552Smckusick *acflag |= ASU; 145*37552Smckusick return (0); 14618Sbill } 147*37552Smckusick return (EPERM); 14818Sbill } 149