diff options
-rw-r--r-- | ChangeLog.txt | 5 | ||||
-rw-r--r-- | ports/darwin/guts/open.c | 10 | ||||
-rw-r--r-- | ports/linux/guts/__xmknodat.c | 5 | ||||
-rw-r--r-- | ports/linux/guts/openat.c | 10 | ||||
-rw-r--r-- | ports/unix/guts/fchmod.c | 2 | ||||
-rw-r--r-- | ports/unix/guts/fchmodat.c | 4 | ||||
-rw-r--r-- | ports/unix/guts/mkdirat.c | 4 | ||||
-rw-r--r-- | ports/unix/guts/mknodat.c | 5 | ||||
-rw-r--r-- | pseudo_client.h | 7 |
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))) |