~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/fs/protect.c


  1 /* This file deals with protection in the file system.  It contains the code
  2  * for four system calls that relate to protection.
  3  *
  4  * The entry points into this file are
  5  *   do_chmod:  perform the CHMOD system call
  6  *   do_chown:  perform the CHOWN system call
  7  *   do_umask:  perform the UMASK system call
  8  *   do_access: perform the ACCESS system call
  9  *   forbidden: check to see if a given access is allowed on a given inode
 10  */
 11 
 12 #include "fs.h"
 13 #include <unistd.h>
 14 #include <minix/callnr.h>
 15 #include "buf.h"
 16 #include "file.h"
 17 #include "fproc.h"
 18 #include "inode.h"
 19 #include "param.h"
 20 #include "super.h"
 21 
 22 /*===========================================================================*
 23  *                              do_chmod                                     *
 24  *===========================================================================*/
 25 PUBLIC int do_chmod()
 26 {
 27 /* Perform the chmod(name, mode) system call. */
 28 
 29   register struct inode *rip;
 30   register int r;
 31 
 32   /* Temporarily open the file. */
 33   if (fetch_name(name, name_length, M3) != OK) return(err_code);
 34   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
 35 
 36   /* Only the owner or the super_user may change the mode of a file.
 37    * No one may change the mode of a file on a read-only file system.
 38    */
 39   if (rip->i_uid != fp->fp_effuid && !super_user)
 40         r = EPERM;
 41   else
 42         r = read_only(rip);
 43 
 44   /* If error, return inode. */
 45   if (r != OK)  {
 46         put_inode(rip);
 47         return(r);
 48   }
 49 
 50   /* Now make the change. Clear setgid bit if file is not in caller's grp */
 51   rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
 52   if (!super_user && rip->i_gid != fp->fp_effgid)rip->i_mode &= ~I_SET_GID_BIT;
 53   rip->i_update |= CTIME;
 54   rip->i_dirt = DIRTY;
 55 
 56   put_inode(rip);
 57   return(OK);
 58 }
 59 
 60 
 61 /*===========================================================================*
 62  *                              do_chown                                     *
 63  *===========================================================================*/
 64 PUBLIC int do_chown()
 65 {
 66 /* Perform the chown(name, owner, group) system call. */
 67 
 68   register struct inode *rip;
 69   register int r;
 70 
 71   /* Temporarily open the file. */
 72   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
 73   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
 74 
 75   /* Not permitted to change the owner of a file on a read-only file sys. */
 76   r = read_only(rip);
 77   if (r == OK) {
 78         /* FS is R/W.  Whether call is allowed depends on ownership, etc. */
 79         if (super_user) {
 80                 /* The super user can do anything. */
 81                 rip->i_uid = owner;     /* others later */
 82         } else {
 83                 /* Regular users can only change groups of their own files. */
 84                 if (rip->i_uid != fp->fp_effuid) r = EPERM;
 85                 if (rip->i_uid != owner) r = EPERM;     /* no giving away */
 86                 if (fp->fp_effgid != group) r = EPERM;
 87         }
 88   }
 89   if (r == OK) {
 90         rip->i_gid = group;
 91         rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
 92         rip->i_update |= CTIME;
 93         rip->i_dirt = DIRTY;
 94   }
 95 
 96   put_inode(rip);
 97   return(r);
 98 }
 99 
100 
101 /*===========================================================================*
102  *                              do_umask                                     *
103  *===========================================================================*/
104 PUBLIC int do_umask()
105 {
106 /* Perform the umask(co_mode) system call. */
107   register mode_t r;
108 
109   r = ~fp->fp_umask;            /* set 'r' to complement of old mask */
110   fp->fp_umask = ~(co_mode & RWX_MODES);
111   return(r);                    /* return complement of old mask */
112 }
113 
114 
115 /*===========================================================================*
116  *                              do_access                                    *
117  *===========================================================================*/
118 PUBLIC int do_access()
119 {
120 /* Perform the access(name, mode) system call. */
121 
122   struct inode *rip;
123   register int r;
124 
125   /* First check to see if the mode is correct. */
126   if ( (mode & ~(R_OK | W_OK | X_OK)) != 0 && mode != F_OK)
127         return(EINVAL);
128 
129   /* Temporarily open the file whose access is to be checked. */
130   if (fetch_name(name, name_length, M3) != OK) return(err_code);
131   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
132 
133   /* Now check the permissions. */
134   r = forbidden(rip, (mode_t) mode);
135   put_inode(rip);
136   return(r);
137 }
138 
139 
140 /*===========================================================================*
141  *                              forbidden                                    *
142  *===========================================================================*/
143 PUBLIC int forbidden(rip, access_desired)
144 register struct inode *rip;     /* pointer to inode to be checked */
145 mode_t access_desired;  /* RWX bits */
146 {
147 /* Given a pointer to an inode, 'rip', and the access desired, determine
148  * if the access is allowed, and if not why not.  The routine looks up the
149  * caller's uid in the 'fproc' table.  If access is allowed, OK is returned
150  * if it is forbidden, EACCES is returned.
151  */
152 
153   register struct inode *old_rip = rip;
154   register struct super_block *sp;
155   register mode_t bits, perm_bits;
156   int r, shift, test_uid, test_gid;
157 
158   if (rip->i_mount == I_MOUNT)  /* The inode is mounted on. */
159         for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
160                 if (sp->s_imount == rip) {
161                         rip = get_inode(sp->s_dev, ROOT_INODE);
162                         break;
163                 } /* if */
164 
165   /* Isolate the relevant rwx bits from the mode. */
166   bits = rip->i_mode;
167   test_uid = (fs_call == ACCESS ? fp->fp_realuid : fp->fp_effuid);
168   test_gid = (fs_call == ACCESS ? fp->fp_realgid : fp->fp_effgid);
169   if (test_uid == SU_UID) {
170         /* Grant read and write permission.  Grant search permission for
171          * directories.  Grant execute permission (for non-directories) if
172          * and only if one of the 'X' bits is set.
173          */
174         if ( (bits & I_TYPE) == I_DIRECTORY ||
175              bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
176                 perm_bits = R_BIT | W_BIT | X_BIT;
177         else
178                 perm_bits = R_BIT | W_BIT;
179   } else {
180         if (test_uid == rip->i_uid) shift = 6;          /* owner */
181         else if (test_gid == rip->i_gid ) shift = 3;    /* group */
182         else shift = 0;                                 /* other */
183         perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
184   }
185 
186   /* If access desired is not a subset of what is allowed, it is refused. */
187   r = OK;
188   if ((perm_bits | access_desired) != perm_bits) r = EACCES;
189 
190   /* Check to see if someone is trying to write on a file system that is
191    * mounted read-only.
192    */
193   if (r == OK)
194         if (access_desired & W_BIT) r = read_only(rip);
195 
196   if (rip != old_rip) put_inode(rip);
197 
198   return(r);
199 }
200 
201 
202 /*===========================================================================*
203  *                              read_only                                    *
204  *===========================================================================*/
205 PUBLIC int read_only(ip)
206 struct inode *ip;               /* ptr to inode whose file sys is to be cked */
207 {
208 /* Check to see if the file system on which the inode 'ip' resides is mounted
209  * read only.  If so, return EROFS, else return OK.
210  */
211 
212   register struct super_block *sp;
213 
214   sp = ip->i_sp;
215   return(sp->s_rd_only ? EROFS : OK);
216 }
217 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.