1 /* Created (MFS based):
2 * June 2011 (Evgeniy Ivanov)
6 #include <minix/vfsif.h>
9 #include "puffs_priv.h"
11 static int in_group(gid_t grp
);
14 /*===========================================================================*
16 *===========================================================================*/
19 /* Perform the chmod(name, mode) system call. */
20 struct puffs_node
*pn
;
23 PUFFS_MAKECRED(pcr
, &global_kcred
);
25 if (global_pu
->pu_ops
.puffs_node_setattr
== NULL
)
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
)
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)
41 /* Return full new mode to caller. */
42 fs_m_out
.m_fs_vfs_chmod
.mode
= pn
->pn_va
.va_mode
;
48 /*===========================================================================*
50 *===========================================================================*/
53 struct puffs_node
*pn
;
55 PUFFS_MAKECRED(pcr
, &global_kcred
);
57 if ((pn
= puffs_pn_nodewalk(global_pu
, 0, &fs_m_in
.m_vfs_fs_chown
.inode
)) == NULL
)
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)
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
;
79 /*===========================================================================*
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
;
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
;
104 perm_bits
= R_BIT
| W_BIT
;
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. */
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
121 if (access_desired
& W_BIT
) {
122 r
= is_readonly_fs
? EROFS
: OK
;
130 /*===========================================================================*
132 *===========================================================================*/
133 static int in_group(gid_t grp
)
136 for(i
= 0; i
< credentials
.vu_ngroups
; i
++)
137 if (credentials
.vu_sgroups
[i
] == grp
)