📄 protect.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/fs/protect.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26100 /* This file deals with protection in the file system. It contains the code
26101 * for four system calls that relate to protection.
26102 *
26103 * The entry points into this file are
26104 * do_chmod: perform the CHMOD system call
26105 * do_chown: perform the CHOWN system call
26106 * do_umask: perform the UMASK system call
26107 * do_access: perform the ACCESS system call
26108 * forbidden: check to see if a given access is allowed on a given inode
26109 */
26110
26111 #include "fs.h"
26112 #include <unistd.h>
26113 #include <minix/callnr.h>
26114 #include "buf.h"
26115 #include "file.h"
26116 #include "fproc.h"
26117 #include "inode.h"
26118 #include "param.h"
26119 #include "super.h"
26120
26121 /*===========================================================================*
26122 * do_chmod *
26123 *===========================================================================*/
26124 PUBLIC int do_chmod()
26125 {
26126 /* Perform the chmod(name, mode) system call. */
26127
26128 register struct inode *rip;
26129 register int r;
26130
26131 /* Temporarily open the file. */
26132 if (fetch_name(name, name_length, M3) != OK) return(err_code);
26133 if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
26134
26135 /* Only the owner or the super_user may change the mode of a file.
26136 * No one may change the mode of a file on a read-only file system.
26137 */
26138 if (rip->i_uid != fp->fp_effuid && !super_user)
26139 r = EPERM;
26140 else
26141 r = read_only(rip);
26142
26143 /* If error, return inode. */
26144 if (r != OK) {
26145 put_inode(rip);
26146 return(r);
26147 }
26148
26149 /* Now make the change. Clear setgid bit if file is not in caller's grp */
26150 rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
26151 if (!super_user && rip->i_gid != fp->fp_effgid)rip->i_mode &= ~I_SET_GID_BIT;
26152 rip->i_update |= CTIME;
26153 rip->i_dirt = DIRTY;
26154
26155 put_inode(rip);
26156 return(OK);
26157 }
26160 /*===========================================================================*
26161 * do_chown *
26162 *===========================================================================*/
26163 PUBLIC int do_chown()
26164 {
26165 /* Perform the chown(name, owner, group) system call. */
26166
26167 register struct inode *rip;
26168 register int r;
26169
26170 /* Temporarily open the file. */
26171 if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
26172 if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
26173
26174 /* Not permitted to change the owner of a file on a read-only file sys. */
26175 r = read_only(rip);
26176 if (r == OK) {
26177 /* FS is R/W. Whether call is allowed depends on ownership, etc. */
26178 if (super_user) {
26179 /* The super user can do anything. */
26180 rip->i_uid = owner; /* others later */
26181 } else {
26182 /* Regular users can only change groups of their own files. */
26183 if (rip->i_uid != fp->fp_effuid) r = EPERM;
26184 if (rip->i_uid != owner) r = EPERM; /* no giving away */
26185 if (fp->fp_effgid != group) r = EPERM;
26186 }
26187 }
26188 if (r == OK) {
26189 rip->i_gid = group;
26190 rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
26191 rip->i_update |= CTIME;
26192 rip->i_dirt = DIRTY;
26193 }
26194
26195 put_inode(rip);
26196 return(r);
26197 }
26200 /*===========================================================================*
26201 * do_umask *
26202 *===========================================================================*/
26203 PUBLIC int do_umask()
26204 {
26205 /* Perform the umask(co_mode) system call. */
26206 register mode_t r;
26207
26208 r = ~fp->fp_umask; /* set 'r' to complement of old mask */
26209 fp->fp_umask = ~(co_mode & RWX_MODES);
26210 return(r); /* return complement of old mask */
26211 }
26214 /*===========================================================================*
26215 * do_access *
26216 *===========================================================================*/
26217 PUBLIC int do_access()
26218 {
26219 /* Perform the access(name, mode) system call. */
26220
26221 struct inode *rip;
26222 register int r;
26223
26224 /* First check to see if the mode is correct. */
26225 if ( (mode & ~(R_OK | W_OK | X_OK)) != 0 && mode != F_OK)
26226 return(EINVAL);
26227
26228 /* Temporarily open the file whose access is to be checked. */
26229 if (fetch_name(name, name_length, M3) != OK) return(err_code);
26230 if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
26231
26232 /* Now check the permissions. */
26233 r = forbidden(rip, (mode_t) mode);
26234 put_inode(rip);
26235 return(r);
26236 }
26239 /*===========================================================================*
26240 * forbidden *
26241 *===========================================================================*/
26242 PUBLIC int forbidden(rip, access_desired)
26243 register struct inode *rip; /* pointer to inode to be checked */
26244 mode_t access_desired; /* RWX bits */
26245 {
26246 /* Given a pointer to an inode, 'rip', and the access desired, determine
26247 * if the access is allowed, and if not why not. The routine looks up the
26248 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
26249 * if it is forbidden, EACCES is returned.
26250 */
26251
26252 register struct inode *old_rip = rip;
26253 register struct super_block *sp;
26254 register mode_t bits, perm_bits;
26255 int r, shift, test_uid, test_gid;
26256
26257 if (rip->i_mount == I_MOUNT) /* The inode is mounted on. */
26258 for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
26259 if (sp->s_imount == rip) {
26260 rip = get_inode(sp->s_dev, ROOT_INODE);
26261 break;
26262 } /* if */
26263
26264 /* Isolate the relevant rwx bits from the mode. */
26265 bits = rip->i_mode;
26266 test_uid = (fs_call == ACCESS ? fp->fp_realuid : fp->fp_effuid);
26267 test_gid = (fs_call == ACCESS ? fp->fp_realgid : fp->fp_effgid);
26268 if (test_uid == SU_UID) {
26269 /* Grant read and write permission. Grant search permission for
26270 * directories. Grant execute permission (for non-directories) if
26271 * and only if one of the 'X' bits is set.
26272 */
26273 if ( (bits & I_TYPE) == I_DIRECTORY ||
26274 bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
26275 perm_bits = R_BIT | W_BIT | X_BIT;
26276 else
26277 perm_bits = R_BIT | W_BIT;
26278 } else {
26279 if (test_uid == rip->i_uid) shift = 6; /* owner */
26280 else if (test_gid == rip->i_gid ) shift = 3; /* group */
26281 else shift = 0; /* other */
26282 perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
26283 }
26284
26285 /* If access desired is not a subset of what is allowed, it is refused. */
26286 r = OK;
26287 if ((perm_bits | access_desired) != perm_bits) r = EACCES;
26288
26289 /* Check to see if someone is trying to write on a file system that is
26290 * mounted read-only.
26291 */
26292 if (r == OK)
26293 if (access_desired & W_BIT) r = read_only(rip);
26294
26295 if (rip != old_rip) put_inode(rip);
26296
26297 return(r);
26298 }
26301 /*===========================================================================*
26302 * read_only *
26303 *===========================================================================*/
26304 PUBLIC int read_only(ip)
26305 struct inode *ip; /* ptr to inode whose file sys is to be cked */
26306 {
26307 /* Check to see if the file system on which the inode 'ip' resides is mounted
26308 * read only. If so, return EROFS, else return OK.
26309 */
26310
26311 register struct super_block *sp;
26312
26313 sp = ip->i_sp;
26314 return(sp->s_rd_only ? EROFS : OK);
26315 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -