170 lines
4.1 KiB
Diff
170 lines
4.1 KiB
Diff
From faa5a3a83ad0cb5e2c303edbfd8cd823c9d94c17 Mon Sep 17 00:00:00 2001
|
|
From: Karel Zak <kzak@redhat.com>
|
|
Date: Thu, 10 Feb 2022 12:03:17 +0100
|
|
Subject: [PATCH] chsh, chfn: remove readline support [CVE-2022-0563]
|
|
|
|
The readline library uses INPUTRC= environment variable to get a path
|
|
to the library config file. When the library cannot parse the
|
|
specified file, it prints an error message containing data from the
|
|
file.
|
|
|
|
Unfortunately, the library does not use secure_getenv() (or a similar
|
|
concept) to avoid vulnerabilities that could occur if set-user-ID or
|
|
set-group-ID programs.
|
|
|
|
Reported-by: Rory Mackie <rory.mackie@trailofbits.com>
|
|
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
|
|
---
|
|
login-utils/Makemodule.am | 2 +-
|
|
login-utils/chfn.c | 16 ++++----------
|
|
login-utils/chsh.c | 45 ++++-----------------------------------
|
|
3 files changed, 9 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
|
|
index 75c0a67..2d0547a 100644
|
|
--- a/login-utils/Makemodule.am
|
|
+++ b/login-utils/Makemodule.am
|
|
@@ -109,7 +109,7 @@ chfn_chsh_sources = \
|
|
login-utils/ch-common.c
|
|
chfn_chsh_cflags = $(SUID_CFLAGS) $(AM_CFLAGS)
|
|
chfn_chsh_ldflags = $(SUID_LDFLAGS) $(AM_LDFLAGS)
|
|
-chfn_chsh_ldadd = libcommon.la $(READLINE_LIBS)
|
|
+chfn_chsh_ldadd = libcommon.la
|
|
|
|
if CHFN_CHSH_PASSWORD
|
|
chfn_chsh_ldadd += -lpam
|
|
diff --git a/login-utils/chfn.c b/login-utils/chfn.c
|
|
index ece5cdc..8f00d15 100644
|
|
--- a/login-utils/chfn.c
|
|
+++ b/login-utils/chfn.c
|
|
@@ -56,11 +56,6 @@
|
|
# include "auth.h"
|
|
#endif
|
|
|
|
-#ifdef HAVE_LIBREADLINE
|
|
-# define _FUNCTION_DEF
|
|
-# include <readline/readline.h>
|
|
-#endif
|
|
-
|
|
struct finfo {
|
|
char *full_name;
|
|
char *office;
|
|
@@ -228,24 +223,21 @@ static char *ask_new_field(struct chfn_control *ctl, const char *question,
|
|
{
|
|
int len;
|
|
char *buf = NULL; /* leave initialized to NULL or getline segfaults */
|
|
-#ifndef HAVE_LIBREADLINE
|
|
size_t dummy = 0;
|
|
-#endif
|
|
|
|
if (!def_val)
|
|
def_val = "";
|
|
+
|
|
while (true) {
|
|
printf("%s [%s]:", question, def_val);
|
|
__fpurge(stdin);
|
|
-#ifdef HAVE_LIBREADLINE
|
|
- rl_bind_key('\t', rl_insert);
|
|
- if ((buf = readline(" ")) == NULL)
|
|
-#else
|
|
+
|
|
putchar(' ');
|
|
fflush(stdout);
|
|
+
|
|
if (getline(&buf, &dummy, stdin) < 0)
|
|
-#endif
|
|
errx(EXIT_FAILURE, _("Aborted."));
|
|
+
|
|
/* remove white spaces from string end */
|
|
ltrim_whitespace((unsigned char *) buf);
|
|
len = rtrim_whitespace((unsigned char *) buf);
|
|
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
|
|
index 3b446be..b7e7017 100644
|
|
--- a/login-utils/chsh.c
|
|
+++ b/login-utils/chsh.c
|
|
@@ -50,7 +50,6 @@
|
|
# include "selinux-utils.h"
|
|
#endif
|
|
|
|
-
|
|
#ifdef HAVE_LIBUSER
|
|
# include <libuser/user.h>
|
|
# include "libuser.h"
|
|
@@ -58,11 +57,6 @@
|
|
# include "auth.h"
|
|
#endif
|
|
|
|
-#ifdef HAVE_LIBREADLINE
|
|
-# define _FUNCTION_DEF
|
|
-# include <readline/readline.h>
|
|
-#endif
|
|
-
|
|
struct sinfo {
|
|
char *username;
|
|
char *shell;
|
|
@@ -121,33 +115,6 @@ static void print_shells(void)
|
|
endusershell();
|
|
}
|
|
|
|
-#ifdef HAVE_LIBREADLINE
|
|
-static char *shell_name_generator(const char *text, int state)
|
|
-{
|
|
- static size_t len;
|
|
- char *s;
|
|
-
|
|
- if (!state) {
|
|
- setusershell();
|
|
- len = strlen(text);
|
|
- }
|
|
-
|
|
- while ((s = getusershell())) {
|
|
- if (strncmp(s, text, len) == 0)
|
|
- return xstrdup(s);
|
|
- }
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static char **shell_name_completion(const char *text,
|
|
- int start __attribute__((__unused__)),
|
|
- int end __attribute__((__unused__)))
|
|
-{
|
|
- rl_attempted_completion_over = 1;
|
|
- return rl_completion_matches(text, shell_name_generator);
|
|
-}
|
|
-#endif
|
|
-
|
|
/*
|
|
* parse_argv () --
|
|
* parse the command line arguments, and fill in "pinfo" with any
|
|
@@ -198,22 +165,18 @@ static char *ask_new_shell(char *question, char *oldshell)
|
|
{
|
|
int len;
|
|
char *ans = NULL;
|
|
-#ifdef HAVE_LIBREADLINE
|
|
- rl_attempted_completion_function = shell_name_completion;
|
|
-#else
|
|
size_t dummy = 0;
|
|
-#endif
|
|
+
|
|
if (!oldshell)
|
|
oldshell = "";
|
|
printf("%s [%s]:", question, oldshell);
|
|
-#ifdef HAVE_LIBREADLINE
|
|
- if ((ans = readline(" ")) == NULL)
|
|
-#else
|
|
+
|
|
putchar(' ');
|
|
fflush(stdout);
|
|
+
|
|
if (getline(&ans, &dummy, stdin) < 0)
|
|
-#endif
|
|
return NULL;
|
|
+
|
|
/* remove the newline at the end of ans. */
|
|
ltrim_whitespace((unsigned char *) ans);
|
|
len = rtrim_whitespace((unsigned char *) ans);
|
|
--
|
|
2.27.0
|
|
|