Blame SOURCES/sudo-1.9.5-CVE-2021-23240-3.patch

9f5db7
diff -up ./src/exec_monitor.c.symbolic-link-attack-3 ./src/exec_monitor.c
9f5db7
--- ./src/exec_monitor.c.symbolic-link-attack-3	2019-10-28 13:27:39.000000000 +0100
9f5db7
+++ ./src/exec_monitor.c	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -613,7 +613,7 @@ exec_monitor(struct command_details *det
9f5db7
 #ifdef HAVE_SELINUX
9f5db7
     if (ISSET(details->flags, CD_RBAC_ENABLED)) {
9f5db7
         if (selinux_setup(details->selinux_role, details->selinux_type,
9f5db7
-            details->tty, io_fds[SFD_SLAVE]) == -1)
9f5db7
+            details->tty, io_fds[SFD_SLAVE], true) == -1)
9f5db7
             goto bad;
9f5db7
     }
9f5db7
 #endif
9f5db7
diff -up ./src/exec_nopty.c.symbolic-link-attack-3 ./src/exec_nopty.c
9f5db7
--- ./src/exec_nopty.c.symbolic-link-attack-3	2019-10-28 13:27:39.000000000 +0100
9f5db7
+++ ./src/exec_nopty.c	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -381,7 +381,7 @@ exec_nopty(struct command_details *detai
9f5db7
 #ifdef HAVE_SELINUX
9f5db7
     if (ISSET(details->flags, CD_RBAC_ENABLED)) {
9f5db7
         if (selinux_setup(details->selinux_role, details->selinux_type,
9f5db7
-		details->tty, -1) == -1) {
9f5db7
+		details->tty, -1, true) == -1) {
9f5db7
 	    cstat->type = CMD_ERRNO;
9f5db7
 	    cstat->val = errno;
9f5db7
 	    debug_return;
9f5db7
diff -up ./src/selinux.c.symbolic-link-attack-3 ./src/selinux.c
9f5db7
--- ./src/selinux.c.symbolic-link-attack-3	2019-10-28 13:27:39.000000000 +0100
9f5db7
+++ ./src/selinux.c	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -363,7 +363,7 @@ bad:
9f5db7
  */
9f5db7
 int
9f5db7
 selinux_setup(const char *role, const char *type, const char *ttyn,
9f5db7
-    int ptyfd)
9f5db7
+    int ptyfd, bool label_tty)
9f5db7
 {
9f5db7
     int ret = -1;
9f5db7
     debug_decl(selinux_setup, SUDO_DEBUG_SELINUX)
9f5db7
@@ -392,7 +392,7 @@ selinux_setup(const char *role, const ch
9f5db7
     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new context %s", __func__,
9f5db7
 	se_state.new_context);
9f5db7
     
9f5db7
-    if (relabel_tty(ttyn, ptyfd) == -1) {
9f5db7
+    if (label_tty && relabel_tty(ttyn, ptyfd) == -1) {
9f5db7
 	sudo_warn(U_("unable to set tty context to %s"), se_state.new_context);
9f5db7
 	goto done;
9f5db7
     }
9f5db7
@@ -408,6 +408,28 @@ done:
9f5db7
     debug_return_int(ret);
9f5db7
 }
9f5db7
 
9f5db7
+int
9f5db7
+selinux_setcon(void)
9f5db7
+{
9f5db7
+    debug_decl(selinux_setcon, SUDO_DEBUG_SELINUX);
9f5db7
+
9f5db7
+    if (setexeccon(se_state.new_context)) {
9f5db7
+	sudo_warn(U_("unable to set exec context to %s"), se_state.new_context);
9f5db7
+	if (se_state.enforcing)
9f5db7
+	    debug_return_int(-1);
9f5db7
+    }
9f5db7
+
9f5db7
+#ifdef HAVE_SETKEYCREATECON
9f5db7
+    if (setkeycreatecon(se_state.new_context)) {
9f5db7
+	sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context);
9f5db7
+	if (se_state.enforcing)
9f5db7
+	    debug_return_int(-1);
9f5db7
+    }
9f5db7
+#endif /* HAVE_SETKEYCREATECON */
9f5db7
+
9f5db7
+    debug_return_int(0);
9f5db7
+}
9f5db7
+
9f5db7
 void
9f5db7
 selinux_execve(int fd, const char *path, char *const argv[], char *envp[],
9f5db7
     bool noexec)
9f5db7
@@ -424,19 +446,9 @@ selinux_execve(int fd, const char *path,
9f5db7
 	debug_return;
9f5db7
     }
9f5db7
 
9f5db7
-    if (setexeccon(se_state.new_context)) {
9f5db7
-	sudo_warn(U_("unable to set exec context to %s"), se_state.new_context);
9f5db7
-	if (se_state.enforcing)
9f5db7
-	    debug_return;
9f5db7
-    }
9f5db7
-
9f5db7
-#ifdef HAVE_SETKEYCREATECON
9f5db7
-    if (setkeycreatecon(se_state.new_context)) {
9f5db7
-	sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context);
9f5db7
-	if (se_state.enforcing)
9f5db7
-	    debug_return;
9f5db7
-    }
9f5db7
-#endif /* HAVE_SETKEYCREATECON */
9f5db7
+    /* Set SELinux exec and keycreate contexts. */
9f5db7
+    if (selinux_setcon() == -1)
9f5db7
+	debug_return;
9f5db7
 
9f5db7
     /*
9f5db7
      * Build new argv with sesh as argv[0].
9f5db7
diff -up ./src/sudo.c.symbolic-link-attack-3 ./src/sudo.c
9f5db7
--- ./src/sudo.c.symbolic-link-attack-3	2021-02-02 17:12:32.773182386 +0100
9f5db7
+++ ./src/sudo.c	2021-02-02 17:12:48.510964009 +0100
9f5db7
@@ -971,10 +971,6 @@ run_command(struct command_details *deta
9f5db7
     case CMD_WSTATUS:
9f5db7
 	/* Command ran, exited or was killed. */
9f5db7
 	status = cstat.val;
9f5db7
-#ifdef HAVE_SELINUX
9f5db7
-	if (ISSET(details->flags, CD_SUDOEDIT_COPY))
9f5db7
-	    break;
9f5db7
-#endif
9f5db7
 	sudo_debug_printf(SUDO_DEBUG_DEBUG,
9f5db7
 	    "calling policy close with wait status %d", status);
9f5db7
 	policy_close(&policy_plugin, status, 0);
9f5db7
diff -up ./src/sudo_edit.c.symbolic-link-attack-3 ./src/sudo_edit.c
9f5db7
--- ./src/sudo_edit.c.symbolic-link-attack-3	2021-02-02 17:11:32.380020435 +0100
9f5db7
+++ ./src/sudo_edit.c	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -757,28 +757,54 @@ bad:
9f5db7
 
9f5db7
 #ifdef HAVE_SELINUX
9f5db7
 static int
9f5db7
+selinux_run_helper(char *argv[], char *envp[])
9f5db7
+{
9f5db7
+    int status, ret = SESH_ERR_FAILURE;
9f5db7
+    const char *sesh;
9f5db7
+    pid_t child, pid;
9f5db7
+    debug_decl(selinux_run_helper, SUDO_DEBUG_EDIT);
9f5db7
+
9f5db7
+    sesh = sudo_conf_sesh_path();
9f5db7
+    if (sesh == NULL) {
9f5db7
+	sudo_warnx("internal error: sesh path not set");
9f5db7
+	debug_return_int(-1);
9f5db7
+    }
9f5db7
+
9f5db7
+    child = sudo_debug_fork();
9f5db7
+    switch (child) {
9f5db7
+    case -1:
9f5db7
+	sudo_warn(U_("unable to fork"));
9f5db7
+	break;
9f5db7
+    case 0:
9f5db7
+	/* child runs sesh in new context */
9f5db7
+	if (selinux_setcon() == 0)
9f5db7
+	    execve(sesh, argv, envp);
9f5db7
+	_exit(SESH_ERR_FAILURE);
9f5db7
+    default:
9f5db7
+	/* parent waits */
9f5db7
+	do {
9f5db7
+	    pid = waitpid(child, &status, 0);
9f5db7
+	} while (pid == -1 && errno == EINTR);
9f5db7
+
9f5db7
+	ret = WIFSIGNALED(status) ? SESH_ERR_KILLED : WEXITSTATUS(status);
9f5db7
+    }
9f5db7
+
9f5db7
+    debug_return_int(ret);
9f5db7
+}
9f5db7
+
9f5db7
+static int
9f5db7
 selinux_edit_create_tfiles(struct command_details *command_details,
9f5db7
     struct tempfile *tf, char *files[], int nfiles)
9f5db7
 {
9f5db7
     char **sesh_args, **sesh_ap;
9f5db7
     int i, rc, sesh_nargs;
9f5db7
     struct stat sb;
9f5db7
-    struct command_details saved_command_details;
9f5db7
     debug_decl(selinux_edit_create_tfiles, SUDO_DEBUG_EDIT)
9f5db7
-    
9f5db7
-    /* Prepare selinux stuff (setexeccon) */
9f5db7
-    if (selinux_setup(command_details->selinux_role,
9f5db7
-	command_details->selinux_type, NULL, -1) != 0)
9f5db7
-	debug_return_int(-1);
9f5db7
 
9f5db7
     if (nfiles < 1)
9f5db7
 	debug_return_int(0);
9f5db7
 
9f5db7
     /* Construct common args for sesh */
9f5db7
-    memcpy(&saved_command_details, command_details, sizeof(struct command_details));
9f5db7
-    command_details->command = _PATH_SUDO_SESH;
9f5db7
-    command_details->flags |= CD_SUDOEDIT_COPY;
9f5db7
-    
9f5db7
     sesh_nargs = 4 + (nfiles * 2) + 1;
9f5db7
     sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
9f5db7
     if (sesh_args == NULL) {
9f5db7
@@ -791,6 +817,7 @@ selinux_edit_create_tfiles(struct comman
9f5db7
 	*sesh_ap++ = "-h";
9f5db7
     *sesh_ap++ = "0";
9f5db7
 
9f5db7
+    /* XXX - temp files should be created with user's context */
9f5db7
     for (i = 0; i < nfiles; i++) {
9f5db7
 	char *tfile, *ofile = files[i];
9f5db7
 	int tfd;
9f5db7
@@ -820,8 +847,7 @@ selinux_edit_create_tfiles(struct comman
9f5db7
     *sesh_ap = NULL;
9f5db7
 
9f5db7
     /* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */
9f5db7
-    command_details->argv = sesh_args;
9f5db7
-    rc = run_command(command_details);
9f5db7
+    rc = selinux_run_helper(sesh_args, command_details->envp);
9f5db7
     switch (rc) {
9f5db7
     case SESH_SUCCESS:
9f5db7
 	break;
9f5db7
@@ -829,15 +855,12 @@ selinux_edit_create_tfiles(struct comman
9f5db7
 	sudo_fatalx(U_("sesh: internal error: odd number of paths"));
9f5db7
     case SESH_ERR_NO_FILES:
9f5db7
 	sudo_fatalx(U_("sesh: unable to create temporary files"));
9f5db7
+    case SESH_ERR_KILLED:
9f5db7
+	sudo_fatalx(U_("sesh: killed by a signal"));
9f5db7
     default:
9f5db7
 	sudo_fatalx(U_("sesh: unknown error %d"), rc);
9f5db7
     }
9f5db7
 
9f5db7
-    /* Restore saved command_details. */
9f5db7
-    command_details->command = saved_command_details.command;
9f5db7
-    command_details->flags = saved_command_details.flags;
9f5db7
-    command_details->argv = saved_command_details.argv;
9f5db7
-    
9f5db7
     /* Chown to user's UID so they can edit the temporary files. */
9f5db7
     for (i = 0; i < nfiles; i++) {
9f5db7
 	if (chown(tf[i].tfile, user_details.uid, user_details.gid) != 0) {
9f5db7
@@ -858,24 +881,14 @@ selinux_edit_copy_tfiles(struct command_
9f5db7
 {
9f5db7
     char **sesh_args, **sesh_ap;
9f5db7
     int i, rc, sesh_nargs, ret = 1;
9f5db7
-    struct command_details saved_command_details;
9f5db7
     struct timespec ts;
9f5db7
     struct stat sb;
9f5db7
     debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT)
9f5db7
-    
9f5db7
-    /* Prepare selinux stuff (setexeccon) */
9f5db7
-    if (selinux_setup(command_details->selinux_role,
9f5db7
-	command_details->selinux_type, NULL, -1) != 0)
9f5db7
-	debug_return_int(1);
9f5db7
 
9f5db7
     if (nfiles < 1)
9f5db7
 	debug_return_int(0);
9f5db7
 
9f5db7
     /* Construct common args for sesh */
9f5db7
-    memcpy(&saved_command_details, command_details, sizeof(struct command_details));
9f5db7
-    command_details->command = _PATH_SUDO_SESH;
9f5db7
-    command_details->flags |= CD_SUDOEDIT_COPY;
9f5db7
-    
9f5db7
     sesh_nargs = 3 + (nfiles * 2) + 1;
9f5db7
     sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
9f5db7
     if (sesh_args == NULL) {
9f5db7
@@ -913,32 +926,29 @@ selinux_edit_copy_tfiles(struct command_
9f5db7
 
9f5db7
     if (sesh_ap - sesh_args > 3) {
9f5db7
 	/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
9f5db7
-	command_details->argv = sesh_args;
9f5db7
-	rc = run_command(command_details);
9f5db7
+	rc = selinux_run_helper(sesh_args, command_details->envp);
9f5db7
 	switch (rc) {
9f5db7
 	case SESH_SUCCESS:
9f5db7
 	    ret = 0;
9f5db7
 	    break;
9f5db7
 	case SESH_ERR_NO_FILES:
9f5db7
 	    sudo_warnx(U_("unable to copy temporary files back to their original location"));
9f5db7
-	    sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
9f5db7
 	    break;
9f5db7
 	case SESH_ERR_SOME_FILES:
9f5db7
 	    sudo_warnx(U_("unable to copy some of the temporary files back to their original location"));
9f5db7
-	    sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
9f5db7
+	    break;
9f5db7
+	case SESH_ERR_KILLED:
9f5db7
+	    sudo_warnx(U_("sesh: killed by a signal"));
9f5db7
 	    break;
9f5db7
 	default:
9f5db7
 	    sudo_warnx(U_("sesh: unknown error %d"), rc);
9f5db7
 	    break;
9f5db7
 	}
9f5db7
+	if (ret != 0)
9f5db7
+	    sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
9f5db7
     }
9f5db7
     free(sesh_args);
9f5db7
 
9f5db7
-    /* Restore saved command_details. */
9f5db7
-    command_details->command = saved_command_details.command;
9f5db7
-    command_details->flags = saved_command_details.flags;
9f5db7
-    command_details->argv = saved_command_details.argv;
9f5db7
-
9f5db7
     debug_return_int(ret);
9f5db7
 }
9f5db7
 #endif /* HAVE_SELINUX */
9f5db7
@@ -990,6 +1000,15 @@ sudo_edit(struct command_details *comman
9f5db7
 	goto cleanup;
9f5db7
     }
9f5db7
 
9f5db7
+#ifdef HAVE_SELINUX
9f5db7
+    /* Compute new SELinux security context. */
9f5db7
+    if (ISSET(command_details->flags, CD_RBAC_ENABLED)) {
9f5db7
+	if (selinux_setup(command_details->selinux_role,
9f5db7
+		command_details->selinux_type, NULL, -1, false) != 0)
9f5db7
+	    goto cleanup;
9f5db7
+    }
9f5db7
+#endif
9f5db7
+
9f5db7
     /* Copy editor files to temporaries. */
9f5db7
     tf = calloc(nfiles, sizeof(*tf));
9f5db7
     if (tf == NULL) {
9f5db7
@@ -1025,6 +1044,7 @@ sudo_edit(struct command_details *comman
9f5db7
     /*
9f5db7
      * Run the editor with the invoking user's creds,
9f5db7
      * keeping track of the time spent in the editor.
9f5db7
+     * XXX - should run editor with user's context
9f5db7
      */
9f5db7
     if (sudo_gettime_real(&times[0]) == -1) {
9f5db7
 	sudo_warn(U_("unable to read the clock"));
9f5db7
diff -up ./src/sudo_exec.h.symbolic-link-attack-3 ./src/sudo_exec.h
9f5db7
--- ./src/sudo_exec.h.symbolic-link-attack-3	2021-02-02 17:11:32.380020435 +0100
9f5db7
+++ ./src/sudo_exec.h	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -73,6 +73,7 @@
9f5db7
  */
9f5db7
 #define SESH_SUCCESS	    0		/* successful operation */
9f5db7
 #define SESH_ERR_FAILURE    1		/* unspecified error */
9f5db7
+#define SESH_ERR_KILLED     2		/* killed by a signal */
9f5db7
 #define SESH_ERR_INVALID    30		/* invalid -e arg value */
9f5db7
 #define SESH_ERR_BAD_PATHS  31		/* odd number of paths */
9f5db7
 #define SESH_ERR_NO_FILES   32		/* copy error, no files copied */
9f5db7
diff -up ./src/sudo.h.symbolic-link-attack-3 ./src/sudo.h
9f5db7
--- ./src/sudo.h.symbolic-link-attack-3	2019-10-28 13:28:52.000000000 +0100
9f5db7
+++ ./src/sudo.h	2021-02-02 17:11:32.382020407 +0100
9f5db7
@@ -135,12 +135,11 @@ struct user_details {
9f5db7
 #define CD_USE_PTY		0x001000
9f5db7
 #define CD_SET_UTMP		0x002000
9f5db7
 #define CD_EXEC_BG		0x004000
9f5db7
-#define CD_SUDOEDIT_COPY	0x008000
9f5db7
-#define CD_SUDOEDIT_FOLLOW	0x010000
9f5db7
-#define CD_SUDOEDIT_CHECKDIR	0x020000
9f5db7
-#define CD_SET_GROUPS		0x040000
9f5db7
-#define CD_LOGIN_SHELL		0x080000
9f5db7
-#define CD_OVERRIDE_UMASK	0x100000
9f5db7
+#define CD_SUDOEDIT_FOLLOW	0x008000
9f5db7
+#define CD_SUDOEDIT_CHECKDIR	0x010000
9f5db7
+#define CD_SET_GROUPS		0x020000
9f5db7
+#define CD_LOGIN_SHELL		0x040000
9f5db7
+#define CD_OVERRIDE_UMASK	0x080000
9f5db7
 
9f5db7
 struct preserved_fd {
9f5db7
     TAILQ_ENTRY(preserved_fd) entries;
9f5db7
@@ -240,7 +239,8 @@ int os_init_openbsd(int argc, char *argv
9f5db7
 /* selinux.c */
9f5db7
 int selinux_restore_tty(void);
9f5db7
 int selinux_setup(const char *role, const char *type, const char *ttyn,
9f5db7
-    int ttyfd);
9f5db7
+    int ttyfd, bool label_tty);
9f5db7
+int selinux_setcon(void);
9f5db7
 void selinux_execve(int fd, const char *path, char *const argv[],
9f5db7
     char *envp[], bool noexec);
9f5db7