xref: /minix3/minix/fs/mfs/protect.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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