2727#include <assert.h>
2828#include <errno.h>
2929#include <fcntl.h>
30+ #include <unistd.h>
3031
3132#include <nuttx/fs/fs.h>
3233#include <nuttx/rwsem.h>
@@ -121,49 +122,89 @@ void inode_runlock(void)
121122}
122123
123124/****************************************************************************
124- * Name: inode_checkperm
125+ * Name: _inode_checkmode
125126 *
126127 * Description:
127- * Validate that 'inode' can be opened with the access described by
128- * 'oflags'. Two sequential checks are performed:
128+ * Test effective credentials against 'inode' for 'amode' access.
129+ * Kernel threads always pass.
129130 *
130- * 1. Operation-support check (all inode types, unconditional):
131- * Verifies the driver exposes the read/write entry points required by
132- * 'oflags'. Returns -ENXIO when ops are NULL and -EACCES when the
133- * required entry point is absent. Pseudo-directory inodes
134- * (INODE_IS_PSEUDODIR) are exempted from this step.
131+ * Returned Value:
132+ * Zero (OK) or -EACCES.
135133 *
136- * 2. UNIX permission check (pseudo-filesystem inodes only):
137- * Compares effective uid/gid against i_mode owner/group/other bits.
138- * Mountpoint inodes and kernel threads are unconditionally exempted.
139- * Requires CONFIG_PSEUDOFS_ATTRIBUTES and CONFIG_SCHED_USER_IDENTITY;
140- * when either option is disabled this step is a no-op.
134+ ****************************************************************************/
135+
136+ #if defined(CONFIG_PSEUDOFS_ATTRIBUTES ) && defined(CONFIG_SCHED_USER_IDENTITY )
137+ static int _inode_checkmode (FAR struct inode * inode , int amode )
138+ {
139+ FAR struct tcb_s * rtcb ;
140+ mode_t perm ;
141+ uid_t uid ;
142+ gid_t gid ;
143+
144+ /* Kernel threads are always granted access */
145+
146+ rtcb = nxsched_self ();
147+ if ((rtcb -> flags & TCB_FLAG_TTYPE_MASK ) == TCB_FLAG_TTYPE_KERNEL )
148+ {
149+ return OK ;
150+ }
151+
152+ /* Use effective credentials */
153+
154+ DEBUGASSERT (rtcb -> group != NULL );
155+ uid = rtcb -> group -> tg_euid ;
156+ gid = rtcb -> group -> tg_egid ;
157+
158+ /* Select the applicable permission-bit triplet */
159+
160+ if (uid == inode -> i_owner )
161+ {
162+ perm = (inode -> i_mode >> 6 ) & 7 ;
163+ }
164+ else if (gid == inode -> i_group )
165+ {
166+ perm = (inode -> i_mode >> 3 ) & 7 ;
167+ }
168+ else
169+ {
170+ perm = inode -> i_mode & 7 ;
171+ }
172+
173+ /* Every requested bit must be present in the selected triplet */
174+
175+ if ((amode & perm ) != amode )
176+ {
177+ return - EACCES ;
178+ }
179+
180+ return OK ;
181+ }
182+ #endif /* CONFIG_PSEUDOFS_ATTRIBUTES && CONFIG_SCHED_USER_IDENTITY */
183+
184+ /****************************************************************************
185+ * Name: inode_checkperm
186+ *
187+ * Description:
188+ * Validate open access to 'inode' for 'oflags'. Checks driver operation
189+ * support, then pseudo-filesystem mode bits when enabled. Mountpoints
190+ * are exempt from mode checks.
141191 *
142192 * Input Parameters:
143193 * inode - The inode to check
144194 * oflags - Open flags (O_RDONLY / O_WRONLY / O_RDWR)
145195 *
146196 * Returned Value:
147- * Zero (OK) on success. Negated errno on failure:
148- * -ENXIO ops pointer is NULL
149- * -EACCES required operation not supported, or permission denied
197+ * Zero (OK) on success, or a negated errno on failure.
150198 *
151199 ****************************************************************************/
152200
153201int inode_checkperm (FAR struct inode * inode , int oflags )
154202{
155203#if defined(CONFIG_PSEUDOFS_ATTRIBUTES ) && defined(CONFIG_SCHED_USER_IDENTITY )
156- FAR struct tcb_s * rtcb ;
157- mode_t perm ;
158- uid_t uid ;
159- gid_t gid ;
204+ int amode = 0 ;
160205#endif
161206 FAR const struct file_operations * ops ;
162207
163- /* === Step 1: operation-support check === */
164-
165- /* Pseudo-directories carry no ops and are always accessible */
166-
167208 if (INODE_IS_PSEUDODIR (inode ))
168209 {
169210 return OK ;
@@ -185,61 +226,61 @@ int inode_checkperm(FAR struct inode *inode, int oflags)
185226
186227#if defined(CONFIG_PSEUDOFS_ATTRIBUTES ) && defined(CONFIG_SCHED_USER_IDENTITY )
187228
188- /* === Step 2: UNIX permission check (pseudo-filesystem inodes only) === */
189-
190- /* Mountpoints delegate permission enforcement to the underlying
191- * filesystem
192- */
193-
194229 if (INODE_IS_MOUNTPT (inode ))
195230 {
196231 return OK ;
197232 }
198233
199- /* Kernel threads are always granted access */
234+ if ((oflags & O_RDOK ) != 0 )
235+ {
236+ amode |= R_OK ;
237+ }
200238
201- rtcb = nxsched_self ();
202- if ((rtcb -> flags & TCB_FLAG_TTYPE_MASK ) == TCB_FLAG_TTYPE_KERNEL )
239+ if ((oflags & O_WROK ) != 0 )
203240 {
204- return OK ;
241+ amode |= W_OK ;
205242 }
206243
207- /* Use effective credentials */
244+ return _inode_checkmode ( inode , amode );
208245
209- DEBUGASSERT (rtcb -> group != NULL );
210- uid = rtcb -> group -> tg_euid ;
211- gid = rtcb -> group -> tg_egid ;
246+ #endif /* CONFIG_PSEUDOFS_ATTRIBUTES && CONFIG_SCHED_USER_IDENTITY */
212247
213- /* Select the applicable permission-bit triplet */
248+ return OK ;
249+ }
214250
215- if (uid == inode -> i_owner )
216- {
217- perm = (inode -> i_mode >> 6 ) & 7 ;
218- }
219- else if (gid == inode -> i_group )
220- {
221- perm = (inode -> i_mode >> 3 ) & 7 ;
222- }
223- else
224- {
225- perm = inode -> i_mode & 7 ;
226- }
251+ /****************************************************************************
252+ * Name: inode_checkdirperm
253+ *
254+ * Description:
255+ * Check parent directory 'dir' for 'amode' access on pseudo-filesystem
256+ * inodes. NULL 'dir' (root) and mountpoints are exempt.
257+ *
258+ * Input Parameters:
259+ * dir - Parent directory inode, or NULL for a root-level path
260+ * amode - Access mode bitmask (R_OK / W_OK / X_OK)
261+ *
262+ * Returned Value:
263+ * Zero (OK) on success, or -EACCES if permission is denied.
264+ *
265+ ****************************************************************************/
227266
228- /* Bit 2 (value 4) = read permission */
267+ int inode_checkdirperm (FAR struct inode * dir , int amode )
268+ {
269+ #if defined(CONFIG_PSEUDOFS_ATTRIBUTES ) && defined(CONFIG_SCHED_USER_IDENTITY )
229270
230- if ((( oflags & O_RDOK ) != 0 ) && (( perm & 4 ) == 0 ) )
271+ if (dir == NULL )
231272 {
232- return - EACCES ;
273+ return OK ;
233274 }
234275
235- /* Bit 1 (value 2) = write permission */
236-
237- if (((oflags & O_WROK ) != 0 ) && ((perm & 2 ) == 0 ))
276+ if (INODE_IS_MOUNTPT (dir ))
238277 {
239- return - EACCES ;
278+ return OK ;
240279 }
241280
242- #endif /* CONFIG_PSEUDOFS_ATTRIBUTES && CONFIG_SCHED_USER_IDENTITY */
281+ return _inode_checkmode ( dir , amode );
243282
283+ #else
244284 return OK ;
285+ #endif /* CONFIG_PSEUDOFS_ATTRIBUTES && CONFIG_SCHED_USER_IDENTITY */
245286}
0 commit comments