This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new bbc5da95284 libs/libc/unistd: Check X_OK in access().
bbc5da95284 is described below
commit bbc5da952840f849e338ae94013ebd8ada50f465
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 18 00:17:56 2026 +0200
libs/libc/unistd: Check X_OK in access().
access() ignored X_OK: it returned 0 for a file without execute
permission. Also, a successful W_OK check returned before the other
bits were checked.
Check X_OK with the real user and group IDs, as POSIX requires: root
needs any execute bit, another user needs the owner, group or other
execute bit that applies to it. Without CONFIG_SCHED_USER_IDENTITY,
any execute bit is enough. Check W_OK and X_OK one after the other. A
directory is still always accessible.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
libs/libc/unistd/lib_access.c | 74 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 67 insertions(+), 7 deletions(-)
diff --git a/libs/libc/unistd/lib_access.c b/libs/libc/unistd/lib_access.c
index d3ca1f17178..1199422416e 100644
--- a/libs/libc/unistd/lib_access.c
+++ b/libs/libc/unistd/lib_access.c
@@ -27,6 +27,8 @@
#include <nuttx/config.h>
#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -49,9 +51,65 @@
****************************************************************************/
/****************************************************************************
- * Private Function Prototypes
+ * Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: access_xok
+ *
+ * Description:
+ * Return true if the caller may execute the file described by s, with
+ * the real user and group IDs. Root needs any execute bit; another user
+ * needs the owner, group or other execute bit that applies to it.
+ * Without CONFIG_SCHED_USER_IDENTITY, any execute bit is enough.
+ *
+ ****************************************************************************/
+
+static bool access_xok(FAR const struct stat *s)
+{
+ mode_t xbits = S_IXUSR | S_IXGRP | S_IXOTH;
+#ifdef CONFIG_SCHED_USER_IDENTITY
+ uid_t uid = getuid();
+
+ /* Root can execute any file that has at least one execute bit set */
+
+ if (uid != 0)
+ {
+ if (s->st_uid == uid)
+ {
+ xbits = S_IXUSR;
+ }
+ else if (s->st_gid == getgid())
+ {
+ xbits = S_IXGRP;
+ }
+ else
+ {
+# if NGROUPS_MAX > 0
+ gid_t groups[NGROUPS_MAX];
+ int ngroups;
+ int i;
+
+ xbits = S_IXOTH;
+ ngroups = getgroups(NGROUPS_MAX, groups);
+ for (i = 0; i < ngroups; i++)
+ {
+ if (groups[i] == s->st_gid)
+ {
+ xbits = S_IXGRP;
+ break;
+ }
+ }
+# else
+ xbits = S_IXOTH;
+# endif
+ }
+ }
+#endif
+
+ return (s->st_mode & xbits) != 0;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -64,7 +122,8 @@
* to by the path argument for accessibility according to the bit pattern
* contained in amode, using the real user ID in place of the effective
* user ID and the real group ID in place of the effective group ID.
- * As there are no users in NuttX, the function always succeeds.
+ * W_OK needs the owner write bit, and X_OK an execute bit for the
+ * caller. A directory is always accessible.
*
* Input Parameters:
* path - a pointer to the path
@@ -92,13 +151,14 @@ int access(FAR const char *path, int amode)
return 0;
}
- if (amode & W_OK)
+ if ((amode & W_OK) != 0 && (s.st_mode & S_IWUSR) == 0)
{
- if (s.st_mode & S_IWUSR)
- {
- return 0;
- }
+ set_errno(EACCES);
+ return -1;
+ }
+ if ((amode & X_OK) != 0 && !access_xok(&s))
+ {
set_errno(EACCES);
return -1;
}