2 /* This file deals with protection in the file system. It contains the code
3 * for four system calls that relate to protection.
5 * The entry points into this file are
6 * do_chmod: perform the CHMOD and FCHMOD system calls
7 * do_chown: perform the CHOWN and FCHOWN system calls
8 * do_umask: perform the UMASK system call
9 * do_access: perform the ACCESS system call
12 * Jul 2006 (Balazs Gerofi)
17 #include <minix/callnr.h>
22 #include <minix/vfsif.h>
28 /*===========================================================================*
30 *===========================================================================*/
35 struct lookup_req lookup_req
;
36 struct node_details res
;
40 if (call_nr
== CHMOD
) {
41 /* Perform the chmod(name, mode) system call. */
42 if (fetch_name(m_in
.name
, m_in
.name_length
, M3
) != OK
) return(err_code
);
44 /* Fill in lookup request fields */
45 lookup_req
.path
= user_fullpath
;
46 lookup_req
.lastc
= NULL
;
47 lookup_req
.flags
= EAT_PATH
;
50 if ((r
= lookup(&lookup_req
, &res
)) != OK
) return r
;
52 req
.inode_nr
= res
.inode_nr
;
55 else if (call_nr
== FCHMOD
) {
56 if (!(flp
= get_filp(m_in
.m3_i1
))) return err_code
;
57 req
.inode_nr
= flp
->filp_vno
->v_inode_nr
;
58 req
.fs_e
= flp
->filp_vno
->v_fs_e
;
60 else panic(__FILE__
, "do_chmod called with strange call_nr", call_nr
);
62 /* Find vnode, if it's in use. */
63 vp
= find_vnode(req
.fs_e
, req
.inode_nr
);
65 /* Fill in request message fields.*/
66 req
.uid
= fp
->fp_effuid
;
67 req
.gid
= fp
->fp_effgid
;
68 req
.rmode
= m_in
.mode
;
71 if((r
= req_chmod(&req
, &ch_mode
)) != OK
) return r
;
79 /*===========================================================================*
81 *===========================================================================*/
88 struct lookup_req lookup_req
;
89 struct node_details res
;
93 if (call_nr
== CHOWN
) {
94 /* Perform the chmod(name, mode) system call. */
95 if (fetch_name(m_in
.name1
, m_in
.name1_length
, M1
) != OK
) return(err_code
);
97 /* Fill in lookup request fields */
98 lookup_req
.path
= user_fullpath
;
99 lookup_req
.lastc
= NULL
;
100 lookup_req
.flags
= EAT_PATH
;
103 if ((r
= lookup(&lookup_req
, &res
)) != OK
) return r
;
105 req
.inode_nr
= res
.inode_nr
;
108 else if (call_nr
== FCHOWN
) {
109 if (!(flp
= get_filp(m_in
.m1_i1
))) return err_code
;
110 req
.inode_nr
= flp
->filp_vno
->v_inode_nr
;
111 req
.fs_e
= flp
->filp_vno
->v_fs_e
;
113 else panic(__FILE__
, "do_chmod called with strange call_nr", call_nr
);
115 /* Find vnode, if it's in use. */
116 vp
= find_vnode(req
.fs_e
, req
.inode_nr
);
118 /* Fill in request message fields.*/
119 req
.uid
= fp
->fp_effuid
;
120 req
.gid
= fp
->fp_effgid
;
121 req
.newuid
= m_in
.owner
;
122 req
.newgid
= m_in
.group
;
125 r
= req_chown(&req
, &ch_mode
);
128 vp
->v_uid
= m_in
.owner
;
129 vp
->v_gid
= m_in
.group
;
130 vp
->v_mode
= ch_mode
;
137 /*===========================================================================*
139 *===========================================================================*/
140 PUBLIC
int do_umask()
142 /* Perform the umask(co_mode) system call. */
145 r
= ~fp
->fp_umask
; /* set 'r' to complement of old mask */
146 fp
->fp_umask
= ~(m_in
.co_mode
& RWX_MODES
);
147 return(r
); /* return complement of old mask */
151 /*===========================================================================*
153 *===========================================================================*/
154 PUBLIC
int do_access()
156 /* Perform the access(name, mode) system call. */
157 struct access_req req
;
158 struct lookup_req lookup_req
;
159 struct node_details res
;
162 /* First check to see if the mode is correct. */
163 if ( (m_in
.mode
& ~(R_OK
| W_OK
| X_OK
)) != 0 && m_in
.mode
!= F_OK
)
166 if (fetch_name(m_in
.name
, m_in
.name_length
, M3
) != OK
) return(err_code
);
168 /* Fill in lookup request fields */
169 lookup_req
.path
= user_fullpath
;
170 lookup_req
.lastc
= NULL
;
171 lookup_req
.flags
= EAT_PATH
;
174 if ((r
= lookup(&lookup_req
, &res
)) != OK
) return r
;
176 /* Fill in request fields */
178 req
.amode
= m_in
.mode
;
179 req
.inode_nr
= res
.inode_nr
;
180 req
.uid
= fp
->fp_realuid
; /* real user and group id */
181 req
.gid
= fp
->fp_realgid
;
184 return req_access(&req
);
188 /*===========================================================================*
190 *===========================================================================*/
191 PUBLIC
int forbidden(struct vnode
*vp
, mode_t access_desired
)
193 /* Given a pointer to an inode, 'rip', and the access desired, determine
194 * if the access is allowed, and if not why not. The routine looks up the
195 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
196 * if it is forbidden, EACCES is returned.
199 register struct super_block
*sp
;
200 register mode_t bits
, perm_bits
;
203 if (vp
->v_uid
== (uid_t
)-1 || vp
->v_gid
== (gid_t
)-1)
205 printf("forbidden: bad uid/gid in vnode\n");
206 printf("forbidden: last allocated at %s, %d\n", vp
->v_file
, vp
->v_line
);
210 /* Isolate the relevant rwx bits from the mode. */
212 if (fp
->fp_effuid
== SU_UID
) {
213 /* Grant read and write permission. Grant search permission for
214 * directories. Grant execute permission (for non-directories) if
215 * and only if one of the 'X' bits is set.
217 if ( (bits
& I_TYPE
) == I_DIRECTORY
||
218 bits
& ((X_BIT
<< 6) | (X_BIT
<< 3) | X_BIT
))
219 perm_bits
= R_BIT
| W_BIT
| X_BIT
;
221 perm_bits
= R_BIT
| W_BIT
;
223 if (fp
->fp_effuid
== vp
->v_uid
) shift
= 6; /* owner */
224 else if (fp
->fp_effgid
== vp
->v_gid
) shift
= 3; /* group */
225 else shift
= 0; /* other */
226 perm_bits
= (bits
>> shift
) & (R_BIT
| W_BIT
| X_BIT
);
229 /* If access desired is not a subset of what is allowed, it is refused. */
231 if ((perm_bits
| access_desired
) != perm_bits
) {
235 /* Check to see if someone is trying to write on a file system that is
239 if (access_desired
& W_BIT
)
246 /*===========================================================================*
248 *===========================================================================*/
249 PUBLIC
int read_only(vp
)
250 struct vnode
*vp
; /* ptr to inode whose file sys is to be cked */
252 /* Check to see if the file system on which the inode 'ip' resides is mounted
253 * read only. If so, return EROFS, else return OK.
255 register struct vmnt
*mp
;
258 return(mp
->m_flags
? EROFS
: OK
);