xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 37552)
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