1 #include "fs.h" 2 #include "inode.h" 3 #include "super.h" 4 #include <minix/vfsif.h> 5 6 static int in_group(gid_t grp); 7 8 9 /*===========================================================================* 10 * fs_chmod * 11 *===========================================================================*/ 12 int fs_chmod() 13 { 14 /* Perform the chmod(name, mode) system call. */ 15 16 register struct inode *rip; 17 mode_t mode; 18 19 mode = fs_m_in.m_vfs_fs_chmod.mode; 20 21 /* Temporarily open the file. */ 22 if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chmod.inode)) == NULL) 23 return(EINVAL); 24 25 if(rip->i_sp->s_rd_only) { 26 put_inode(rip); 27 return EROFS; 28 } 29 30 /* Now make the change. Clear setgid bit if file is not in caller's grp */ 31 rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES); 32 rip->i_update |= CTIME; 33 IN_MARKDIRTY(rip); 34 35 /* Return full new mode to caller. */ 36 fs_m_out.m_fs_vfs_chmod.mode = rip->i_mode; 37 38 put_inode(rip); 39 return(OK); 40 } 41 42 43 /*===========================================================================* 44 * fs_chown * 45 *===========================================================================*/ 46 int fs_chown() 47 { 48 register struct inode *rip; 49 register int r; 50 51 /* Temporarily open the file. */ 52 if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chown.inode)) == NULL) 53 return(EINVAL); 54 55 /* Not permitted to change the owner of a file on a read-only file sys. */ 56 r = read_only(rip); 57 if (r == OK) { 58 rip->i_uid = fs_m_in.m_vfs_fs_chown.uid; 59 rip->i_gid = fs_m_in.m_vfs_fs_chown.gid; 60 rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); 61 rip->i_update |= CTIME; 62 IN_MARKDIRTY(rip); 63 } 64 65 /* Update caller on current mode, as it may have changed. */ 66 fs_m_out.m_fs_vfs_chown.mode = rip->i_mode; 67 put_inode(rip); 68 69 return(r); 70 } 71 72 73 /*===========================================================================* 74 * forbidden * 75 *===========================================================================*/ 76 int forbidden(struct inode *rip, mode_t access_desired) 77 { 78 /* Given a pointer to an inode, 'rip', and the access desired, determine 79 * if the access is allowed, and if not why not. The routine looks up the 80 * caller's uid in the 'fproc' table. If access is allowed, OK is returned 81 * if it is forbidden, EACCES is returned. 82 */ 83 84 register struct inode *old_rip = rip; 85 mode_t bits, perm_bits; 86 int r, shift; 87 88 /* Isolate the relevant rwx bits from the mode. */ 89 bits = rip->i_mode; 90 if (caller_uid == SU_UID) { 91 /* Grant read and write permission. Grant search permission for 92 * directories. Grant execute permission (for non-directories) if 93 * and only if one of the 'X' bits is set. 94 */ 95 if ( (bits & I_TYPE) == I_DIRECTORY || 96 bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT)) 97 perm_bits = R_BIT | W_BIT | X_BIT; 98 else 99 perm_bits = R_BIT | W_BIT; 100 } else { 101 if (caller_uid == rip->i_uid) shift = 6; /* owner */ 102 else if (caller_gid == rip->i_gid) shift = 3; /* group */ 103 else if (in_group(rip->i_gid) == OK) shift = 3; /* other groups */ 104 else shift = 0; /* other */ 105 perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); 106 } 107 108 /* If access desired is not a subset of what is allowed, it is refused. */ 109 r = OK; 110 if ((perm_bits | access_desired) != perm_bits) r = EACCES; 111 112 /* Check to see if someone is trying to write on a file system that is 113 * mounted read-only. 114 */ 115 if (r == OK) 116 if (access_desired & W_BIT) 117 r = read_only(rip); 118 119 if (rip != old_rip) put_inode(rip); 120 121 return(r); 122 } 123 124 125 /*===========================================================================* 126 * in_group * 127 *===========================================================================*/ 128 static int in_group(gid_t grp) 129 { 130 int i; 131 132 if (credentials.vu_ngroups > NGROUPS_MAX) 133 return(EINVAL); 134 135 for (i = 0; i < credentials.vu_ngroups; i++) 136 if (credentials.vu_sgroups[i] == grp) 137 return(OK); 138 139 return(EINVAL); 140 } 141 142 143 /*===========================================================================* 144 * read_only * 145 *===========================================================================*/ 146 int read_only(ip) 147 struct inode *ip; /* ptr to inode whose file sys is to be cked */ 148 { 149 /* Check to see if the file system on which the inode 'ip' resides is mounted 150 * read only. If so, return EROFS, else return OK. 151 */ 152 153 register struct super_block *sp; 154 155 sp = ip->i_sp; 156 return(sp->s_rd_only ? EROFS : OK); 157 } 158 159