custom message type for VM_INFO
[minix3.git] / lib / libpuffs / protect.c
blob6a127f51305a47f22bc0d05885ba0b7c7620c7ec
1 /* Created (MFS based):
2 * June 2011 (Evgeniy Ivanov)
3 */
5 #include "fs.h"
6 #include <minix/vfsif.h>
8 #include "puffs.h"
9 #include "puffs_priv.h"
11 static int in_group(gid_t grp);
14 /*===========================================================================*
15 * fs_chmod *
16 *===========================================================================*/
17 int fs_chmod(void)
19 /* Perform the chmod(name, mode) system call. */
20 struct puffs_node *pn;
21 mode_t mode;
22 struct vattr va;
23 PUFFS_MAKECRED(pcr, &global_kcred);
25 if (global_pu->pu_ops.puffs_node_setattr == NULL)
26 return(EINVAL);
28 mode = fs_m_in.m_vfs_fs_chmod.mode;
30 if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.m_vfs_fs_chmod.inode)) == NULL)
31 return(EINVAL);
33 puffs_vattr_null(&va);
34 /* Clear setgid bit if file is not in caller's grp */
35 va.va_mode = (pn->pn_va.va_mode & ~ALL_MODES) | (mode & ALL_MODES);
36 va.va_ctime = clock_timespec();
38 if (global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr) != 0)
39 return(EINVAL);
41 /* Return full new mode to caller. */
42 fs_m_out.m_fs_vfs_chmod.mode = pn->pn_va.va_mode;
44 return(OK);
48 /*===========================================================================*
49 * fs_chown *
50 *===========================================================================*/
51 int fs_chown(void)
53 struct puffs_node *pn;
54 struct vattr va;
55 PUFFS_MAKECRED(pcr, &global_kcred);
57 if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.m_vfs_fs_chown.inode)) == NULL)
58 return(EINVAL);
60 /* Not permitted to change the owner of a file on a read-only file sys. */
61 if (!is_readonly_fs) {
62 puffs_vattr_null(&va);
63 va.va_uid = fs_m_in.m_vfs_fs_chown.uid;
64 va.va_gid = fs_m_in.m_vfs_fs_chown.gid;
65 va.va_mode = pn->pn_va.va_mode & ~(I_SET_UID_BIT | I_SET_GID_BIT);
66 va.va_ctime = clock_timespec();
68 if (global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr) != 0)
69 return(EINVAL);
72 /* Update caller on current mode, as it may have changed. */
73 fs_m_out.m_fs_vfs_chown.mode = pn->pn_va.va_mode;
75 return(OK);
79 /*===========================================================================*
80 * forbidden *
81 *===========================================================================*/
82 int forbidden(register struct puffs_node *pn, mode_t access_desired)
84 /* Given a pointer to an pnode, 'pn', and the access desired, determine
85 * if the access is allowed, and if not why not. The routine looks up the
86 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
87 * if it is forbidden, EACCES is returned.
90 register mode_t bits, perm_bits;
91 int r, shift;
93 /* Isolate the relevant rwx bits from the mode. */
94 bits = pn->pn_va.va_mode;
95 if (caller_uid == SU_UID) {
96 /* Grant read and write permission. Grant search permission for
97 * directories. Grant execute permission (for non-directories) if
98 * and only if one of the 'X' bits is set.
100 if ( (bits & I_TYPE) == I_DIRECTORY ||
101 bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
102 perm_bits = R_BIT | W_BIT | X_BIT;
103 else
104 perm_bits = R_BIT | W_BIT;
105 } else {
106 if (caller_uid == pn->pn_va.va_uid) shift = 6; /* owner */
107 else if (caller_gid == pn->pn_va.va_gid) shift = 3; /* group */
108 else if (in_group(pn->pn_va.va_gid) == OK) shift = 3; /* other groups */
109 else shift = 0; /* other */
110 perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
113 /* If access desired is not a subset of what is allowed, it is refused. */
114 r = OK;
115 if ((perm_bits | access_desired) != perm_bits) r = EACCES;
117 /* Check to see if someone is trying to write on a file system that is
118 * mounted read-only.
120 if (r == OK) {
121 if (access_desired & W_BIT) {
122 r = is_readonly_fs ? EROFS : OK;
126 return(r);
130 /*===========================================================================*
131 * in_group *
132 *===========================================================================*/
133 static int in_group(gid_t grp)
135 int i;
136 for(i = 0; i < credentials.vu_ngroups; i++)
137 if (credentials.vu_sgroups[i] == grp)
138 return(OK);
140 return(EINVAL);