./usr/tests/minix-posix/test83 minix-sys
./usr/tests/minix-posix/test84 minix-sys
./usr/tests/minix-posix/test85 minix-sys
+./usr/tests/minix-posix/test86 minix-sys
./usr/tests/minix-posix/test9 minix-sys
./usr/tests/minix-posix/testinterp minix-sys
./usr/tests/minix-posix/testisofs minix-sys
/* The interpreter (loader) needs an fd to the main program,
* which is currently in finalexec
*/
- if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) {
+ if ((r = execi.elf_main_fd =
+ common_open(finalexec, O_RDONLY, 0, TRUE /*for_exec*/)) < 0) {
printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
fullpath, r);
FAILCHECK(r);
/* open core file */
snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
r = core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC,
- CORE_MODE);
+ CORE_MODE, FALSE /*for_exec*/);
if (r < 0) goto core_exit;
/* get process name */
if (copy_path(fullpath, sizeof(fullpath)) != OK)
return(err_code);
- return common_open(fullpath, open_flags, 0 /*omode*/);
+ return common_open(fullpath, open_flags, 0 /*omode*/, FALSE /*for_exec*/);
}
/*===========================================================================*
if (fetch_name(vname, vname_length, fullpath) != OK)
return(err_code);
- return common_open(fullpath, open_flags, create_mode);
+ return common_open(fullpath, open_flags, create_mode, FALSE /*for_exec*/);
}
/*===========================================================================*
* common_open *
*===========================================================================*/
-int common_open(char path[PATH_MAX], int oflags, mode_t omode)
+int common_open(char path[PATH_MAX], int oflags, mode_t omode, int for_exec)
{
/* Common code from do_creat and do_open. */
int b, r, exist = TRUE;
/* Only do the normal open code if we didn't just create the file. */
if (exist) {
- /* Check protections. */
- if ((r = forbidden(fp, vp, bits)) == OK) {
+ /* Check permissions based on the given open flags, except when we are
+ * opening an executable for the purpose of passing a file descriptor
+ * to its interpreter for execution, in which case we check the X bit.
+ */
+ if ((r = forbidden(fp, vp, for_exec ? X_BIT : bits)) == OK) {
/* Opening reg. files, directories, and special files differ */
switch (vp->v_mode & S_IFMT) {
case S_IFREG:
/* open.c */
int do_close(void);
int close_fd(struct fproc *rfp, int fd_nr);
-int common_open(char path[PATH_MAX], int oflags, mode_t omode);
+int common_open(char path[PATH_MAX], int oflags, mode_t omode, int for_exec);
int do_creat(void);
int do_lseek(void);
int do_mknod(void);
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
-81 82 83 84 85
+81 82 83 84 85 86
FILES += t84_h_nonexec.sh
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
- 81 82 83 84 85 sh1 sh2 interp mfs isofs vnd"
+ 81 82 83 84 85 86 sh1 sh2 interp mfs isofs vnd"
tests_no=`expr 0`
# If root, make sure the setuid tests have the correct permissions
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+
+#include "common.h"
+
+/*
+ * Test for dynamic executables with no read permissions. This test relies on
+ * being linked dynamically.
+ */
+int
+main(int argc, char ** argv)
+{
+ char *executable, cp_cmd[PATH_MAX + 9];
+ int status;
+
+ if (strcmp(argv[0], "DO CHECK") == 0)
+ exit(EXIT_SUCCESS);
+
+ start(86);
+
+ /* Make a copy of this binary which is executable-only. */
+ executable = argv[0];
+
+ snprintf(cp_cmd, sizeof(cp_cmd), "cp ../%s .", executable);
+ status = system(cp_cmd);
+ if (status < 0 || !WIFEXITED(status) ||
+ WEXITSTATUS(status) != EXIT_SUCCESS) e(0);
+
+ if (chmod(executable, S_IXUSR) != 0) e(0);
+
+ /* Invoke the changed binary in a child process. */
+ switch (fork()) {
+ case -1:
+ e(0);
+ case 0:
+ execl(executable, "DO CHECK", NULL);
+
+ exit(EXIT_FAILURE);
+ default:
+ if (wait(&status) <= 0) e(0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS)
+ e(0);
+ }
+
+ quit();
+ /* NOTREACHED */
+}