aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.txt5
-rw-r--r--ports/darwin/guts/open.c10
-rw-r--r--ports/linux/guts/__xmknodat.c5
-rw-r--r--ports/linux/guts/openat.c10
-rw-r--r--ports/unix/guts/fchmod.c2
-rw-r--r--ports/unix/guts/fchmodat.c4
-rw-r--r--ports/unix/guts/mkdirat.c4
-rw-r--r--ports/unix/guts/mknodat.c5
-rw-r--r--pseudo_client.h7
9 files changed, 32 insertions, 20 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index f358e79..fec5955 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,8 @@
+2011-05-31:
+ * (seebs) Don't mask in 0100 to filesystem modes for things which
+ are not actually directories, because this breaks the special
+ logic in euidaccess for X_OK.
+
2011-05-25:
* (seebs) fix for ulckpwdf()
diff --git a/ports/darwin/guts/open.c b/ports/darwin/guts/open.c
index 64cb6ad..dba6800 100644
--- a/ports/darwin/guts/open.c
+++ b/ports/darwin/guts/open.c
@@ -6,7 +6,7 @@
* int rc = -1;
*/
- struct stat buf;
+ struct stat buf = { 0 };
int existed = 1;
int save_errno;
@@ -20,10 +20,12 @@
errno = save_errno;
}
- /* because we are not actually root, secretly mask in 0700 to the
- * underlying mode
+ /* because we are not actually root, secretly mask in 0600 to the
+ * underlying mode. The ", 0" is because the only time mode matters
+ * is if a file is going to be created, in which case it's
+ * not a directory.
*/
- rc = real_open(path, flags, PSEUDO_FS_MODE(mode));
+ rc = real_open(path, flags, PSEUDO_FS_MODE(mode, 0));
save_errno = errno;
if (rc != -1) {
diff --git a/ports/linux/guts/__xmknodat.c b/ports/linux/guts/__xmknodat.c
index 49b2f8f..59b4f2f 100644
--- a/ports/linux/guts/__xmknodat.c
+++ b/ports/linux/guts/__xmknodat.c
@@ -31,10 +31,11 @@
return -1;
}
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
- rc = real_open(path, O_CREAT | O_WRONLY | O_EXCL, PSEUDO_FS_MODE(mode));
+ rc = real_open(path, O_CREAT | O_WRONLY | O_EXCL,
+ PSEUDO_FS_MODE(mode, 0));
#else
rc = real_openat(dirfd, path, O_CREAT | O_WRONLY | O_EXCL,
- PSEUDO_FS_MODE(mode));
+ PSEUDO_FS_MODE(mode, 0));
#endif
if (rc == -1) {
return -1;
diff --git a/ports/linux/guts/openat.c b/ports/linux/guts/openat.c
index c245796..14d6c2a 100644
--- a/ports/linux/guts/openat.c
+++ b/ports/linux/guts/openat.c
@@ -30,13 +30,15 @@
errno = save_errno;
}
- /* because we are not actually root, secretly mask in 0700 to the
- * underlying mode
+ /* because we are not actually root, secretly mask in 0600 to the
+ * underlying mode. The ", 0" is because the only time mode matters
+ * is if a file is going to be created, in which case it's
+ * not a directory.
*/
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
- rc = real_open(path, flags, PSEUDO_FS_MODE(mode));
+ rc = real_open(path, flags, PSEUDO_FS_MODE(mode, 0));
#else
- rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode));
+ rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode, 0));
#endif
save_errno = errno;
diff --git a/ports/unix/guts/fchmod.c b/ports/unix/guts/fchmod.c
index 40f62ba..7c6a6ad 100644
--- a/ports/unix/guts/fchmod.c
+++ b/ports/unix/guts/fchmod.c
@@ -16,7 +16,7 @@
}
buf.st_mode = (buf.st_mode & ~07777) | (mode & 07777);
msg = pseudo_client_op_plain(OP_FCHMOD, 0, fd, -1, 0, &buf);
- real_fchmod(fd, PSEUDO_FS_MODE(mode));
+ real_fchmod(fd, PSEUDO_FS_MODE(mode, S_ISDIR(buf.st_mode)));
if (msg && msg->result != RESULT_SUCCEED) {
errno = EPERM;
rc = -1;
diff --git a/ports/unix/guts/fchmodat.c b/ports/unix/guts/fchmodat.c
index 531345d..5095c77 100644
--- a/ports/unix/guts/fchmodat.c
+++ b/ports/unix/guts/fchmodat.c
@@ -47,9 +47,9 @@
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
/* note: if path was a symlink, and AT_NOFOLLOW_SYMLINKS was
* specified, we already bailed previously. */
- real_chmod(path, PSEUDO_FS_MODE(mode));
+ real_chmod(path, PSEUDO_FS_MODE(mode, S_ISDIR(buf.st_mode)));
#else
- real_fchmodat(dirfd, path, PSEUDO_FS_MODE(mode), flags);
+ real_fchmodat(dirfd, path, PSEUDO_FS_MODE(mode, S_ISDIR(buf.st_mode)), flags);
#endif
/* we ignore a failure from underlying fchmod, because pseudo
* may believe you are permitted to change modes that the filesystem
diff --git a/ports/unix/guts/mkdirat.c b/ports/unix/guts/mkdirat.c
index a3d3ca7..97141fc 100644
--- a/ports/unix/guts/mkdirat.c
+++ b/ports/unix/guts/mkdirat.c
@@ -11,9 +11,9 @@
errno = ENOSYS;
return -1;
}
- rc = real_mkdir(path, PSEUDO_FS_MODE(mode));
+ rc = real_mkdir(path, PSEUDO_FS_MODE(mode, 1));
#else
- rc = real_mkdirat(dirfd, path, PSEUDO_FS_MODE(mode));
+ rc = real_mkdirat(dirfd, path, PSEUDO_FS_MODE(mode, 1));
#endif
if (rc != -1) {
struct stat buf;
diff --git a/ports/unix/guts/mknodat.c b/ports/unix/guts/mknodat.c
index 22fe5ce..2b24cd0 100644
--- a/ports/unix/guts/mknodat.c
+++ b/ports/unix/guts/mknodat.c
@@ -24,10 +24,11 @@
return -1;
}
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
- rc = real_open(path, O_CREAT | O_WRONLY | O_EXCL, PSEUDO_FS_MODE(mode));
+ rc = real_open(path, O_CREAT | O_WRONLY | O_EXCL,
+ PSEUDO_FS_MODE(mode, 0));
#else
rc = real_openat(dirfd, path, O_CREAT | O_WRONLY | O_EXCL,
- PSEUDO_FS_MODE(mode));
+ PSEUDO_FS_MODE(mode, 0));
#endif
if (rc == -1) {
return -1;
diff --git a/pseudo_client.h b/pseudo_client.h
index 587f8a3..e3ad02b 100644
--- a/pseudo_client.h
+++ b/pseudo_client.h
@@ -66,8 +66,9 @@ extern char *pseudo_passwd;
extern size_t pseudo_chroot_len;
extern int pseudo_nosymlinkexp;
-/* Root can read, write, and execute files which have no read, write,
- * or execute permissions.
+/* Root can read and write files, and enter directories which have no
+ * read, write, or execute permissions. (But can't execute files without
+ * execute permissions!)
*
* A non-root user can't.
*
@@ -78,6 +79,6 @@ extern int pseudo_nosymlinkexp;
* None of this will behave very sensibly if umask has 0700 bits in it;
* this is a known limitation.
*/
-#define PSEUDO_FS_MODE(mode) ((mode) | S_IRUSR | S_IWUSR | S_IXUSR)
+#define PSEUDO_FS_MODE(mode, isdir) ((mode) | S_IRUSR | S_IWUSR | ((isdir) ? S_IXUSR : 0))
#define PSEUDO_DB_MODE(fs_mode, user_mode) (((fs_mode) & ~0700) | ((user_mode & 0700)))