From 703418fe9d2e3b1e8d594df5788d8001a8116265 Mon Sep 17 00:00:00 2001 From: Jeffrey Bencteux Date: Fri, 30 Jun 2023 19:02:45 +0200 Subject: [PATCH] CVE-2023-40303: ftpd,rcp,rlogin,rsh,rshd,uucpd: fix: check set*id() return values Several setuid(), setgid(), seteuid() and setguid() return values were not checked in ftpd/rcp/rlogin/rsh/rshd/uucpd code potentially leading to potential security issues. CVE: CVE-2023-40303 Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=e4e65c03f4c11292a3e40ef72ca3f194c8bffdd6] Signed-off-by: Jeffrey Bencteux Signed-off-by: Simon Josefsson Signed-off-by: Khem Raj Signed-off-by: Vijay Anusuri --- ftpd/ftpd.c | 10 +++++++--- src/rcp.c | 39 +++++++++++++++++++++++++++++++++------ src/rlogin.c | 11 +++++++++-- src/rsh.c | 25 +++++++++++++++++++++---- src/rshd.c | 20 +++++++++++++++++--- src/uucpd.c | 15 +++++++++++++-- 6 files changed, 100 insertions(+), 20 deletions(-) diff --git a/ftpd/ftpd.c b/ftpd/ftpd.c index 5db88d0..b52b122 100644 --- a/ftpd/ftpd.c +++ b/ftpd/ftpd.c @@ -862,7 +862,9 @@ end_login (struct credentials *pcred) char *remotehost = pcred->remotehost; int atype = pcred->auth_type; - seteuid ((uid_t) 0); + if (seteuid ((uid_t) 0) == -1) + _exit (EXIT_FAILURE); + if (pcred->logged_in) { logwtmp_keep_open (ttyline, "", ""); @@ -1151,7 +1153,8 @@ getdatasock (const char *mode) if (data >= 0) return fdopen (data, mode); - seteuid ((uid_t) 0); + if (seteuid ((uid_t) 0) == -1) + _exit (EXIT_FAILURE); s = socket (ctrl_addr.ss_family, SOCK_STREAM, 0); if (s < 0) goto bad; @@ -1978,7 +1981,8 @@ passive (int epsv, int af) else /* !AF_INET6 */ ((struct sockaddr_in *) &pasv_addr)->sin_port = 0; - seteuid ((uid_t) 0); + if (seteuid ((uid_t) 0) == -1) + _exit (EXIT_FAILURE); if (bind (pdata, (struct sockaddr *) &pasv_addr, pasv_addrlen) < 0) { if (seteuid ((uid_t) cred.uid)) diff --git a/src/rcp.c b/src/rcp.c index bafa35f..366295c 100644 --- a/src/rcp.c +++ b/src/rcp.c @@ -347,14 +347,23 @@ main (int argc, char *argv[]) if (from_option) { /* Follow "protocol", send data. */ response (); - setuid (userid); + + if (setuid (userid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); + } + source (argc, argv); exit (errs); } if (to_option) { /* Receive data. */ - setuid (userid); + if (setuid (userid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); + } + sink (argc, argv); exit (errs); } @@ -539,7 +548,11 @@ toremote (char *targ, int argc, char *argv[]) if (response () < 0) exit (EXIT_FAILURE); free (bp); - setuid (userid); + + if (setuid (userid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); + } } source (1, argv + i); close (rem); @@ -634,7 +647,12 @@ tolocal (int argc, char *argv[]) ++errs; continue; } - seteuid (userid); + + if (seteuid (userid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); + } + #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT sslen = sizeof (ss); (void) getpeername (rem, (struct sockaddr *) &ss, &sslen); @@ -647,7 +665,12 @@ tolocal (int argc, char *argv[]) #endif vect[0] = target; sink (1, vect); - seteuid (effuid); + + if (seteuid (effuid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); + } + close (rem); rem = -1; #ifdef SHISHI @@ -1453,7 +1476,11 @@ susystem (char *s, int userid) return (127); case 0: - setuid (userid); + if (setuid (userid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); + } + execl (PATH_BSHELL, "sh", "-c", s, NULL); _exit (127); } diff --git a/src/rlogin.c b/src/rlogin.c index e5e11a7..6b38901 100644 --- a/src/rlogin.c +++ b/src/rlogin.c @@ -649,8 +649,15 @@ try_connect: /* Now change to the real user ID. We have to be set-user-ID root to get the privileged port that rcmd () uses. We now want, however, to run as the real user who invoked us. */ - seteuid (uid); - setuid (uid); + if (seteuid (uid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); + } + + if (setuid (uid) == -1) + { + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); + } doit (&osmask); /* The old mask will activate SIGURG and SIGUSR1! */ diff --git a/src/rsh.c b/src/rsh.c index bd70372..b451a70 100644 --- a/src/rsh.c +++ b/src/rsh.c @@ -278,8 +278,17 @@ main (int argc, char **argv) { if (asrsh) *argv = (char *) "rlogin"; - seteuid (getuid ()); - setuid (getuid ()); + + if (seteuid (getuid ()) == -1) + { + error (EXIT_FAILURE, errno, "seteuid() failed"); + } + + if (setuid (getuid ()) == -1) + { + error (EXIT_FAILURE, errno, "setuid() failed"); + } + execv (PATH_RLOGIN, argv); error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN); } @@ -543,8 +552,16 @@ try_connect: error (0, errno, "setsockopt DEBUG (ignored)"); } - seteuid (uid); - setuid (uid); + if (seteuid (uid) == -1) + { + error (EXIT_FAILURE, errno, "seteuid() failed"); + } + + if (setuid (uid) == -1) + { + error (EXIT_FAILURE, errno, "setuid() failed"); + } + #ifdef HAVE_SIGACTION sigemptyset (&sigs); sigaddset (&sigs, SIGINT); diff --git a/src/rshd.c b/src/rshd.c index b824a10..8cdcd06 100644 --- a/src/rshd.c +++ b/src/rshd.c @@ -1848,8 +1848,18 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen) pwd->pw_shell = PATH_BSHELL; /* Set the gid, then uid to become the user specified by "locuser" */ - setegid ((gid_t) pwd->pw_gid); - setgid ((gid_t) pwd->pw_gid); + if (setegid ((gid_t) pwd->pw_gid) == -1) + { + rshd_error ("Cannot drop privileges (setegid() failed)\n"); + exit (EXIT_FAILURE); + } + + if (setgid ((gid_t) pwd->pw_gid) == -1) + { + rshd_error ("Cannot drop privileges (setgid() failed)\n"); + exit (EXIT_FAILURE); + } + #ifdef HAVE_INITGROUPS initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */ #endif @@ -1871,7 +1881,11 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen) } #endif /* WITH_PAM */ - setuid ((uid_t) pwd->pw_uid); + if (setuid ((uid_t) pwd->pw_uid) == -1) + { + rshd_error ("Cannot drop privileges (setuid() failed)\n"); + exit (EXIT_FAILURE); + } /* We'll execute the client's command in the home directory * of locuser. Note, that the chdir must be executed after diff --git a/src/uucpd.c b/src/uucpd.c index 55c3d44..6aba294 100644 --- a/src/uucpd.c +++ b/src/uucpd.c @@ -254,7 +254,12 @@ doit (struct sockaddr *sap, socklen_t salen) sprintf (Username, "USER=%s", user); sprintf (Logname, "LOGNAME=%s", user); dologin (pw, sap, salen); - setgid (pw->pw_gid); + + if (setgid (pw->pw_gid) == -1) + { + fprintf (stderr, "setgid() failed"); + return; + } #ifdef HAVE_INITGROUPS initgroups (pw->pw_name, pw->pw_gid); #endif @@ -263,7 +268,13 @@ doit (struct sockaddr *sap, socklen_t salen) fprintf (stderr, "Login incorrect."); return; } - setuid (pw->pw_uid); + + if (setuid (pw->pw_uid) == -1) + { + fprintf (stderr, "setuid() failed"); + return; + } + execl (uucico_location, "uucico", NULL); perror ("uucico server: execl"); } -- 2.25.1