]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/, src/: Add checks for fd omission
authorSkyler Ferrante <sjf5462@rit.edu>
Fri, 8 Mar 2024 17:53:21 +0000 (12:53 -0500)
committerAlejandro Colomar <alx@kernel.org>
Wed, 13 Mar 2024 22:19:51 +0000 (23:19 +0100)
Adding function check_fds to new file fd.c. The function check_fds
should be called in every setuid/setgid program.

Co-developed-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: d2f2c1877a30 ("Adding checks for fd omission")
Link: <https://github.com/shadow-maint/shadow/pull/964>
Link: <https://inbox.sourceware.org/libc-alpha/ZeyujhVRsDTUNUtw@debian/T/>
[alx: It seems we shouldn't need this, as libc does it for us.  But it ]
[     shouldn't hurt either.  Let's be paranoic.                       ]
Cc: <Guillem Jover <guillem@hadrons.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Skyler Ferrante (RIT Student)" <sjf5462@rit.edu>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Brauner <christian@brauner.io>
Cc: Rich Felker <dalias@libc.org>
Cc: Andreas Schwab <schwab@linux-m68k.org>
Cc: Thorsten Glaser <tg@mirbsd.de>
Cc: NRK <nrk@disroot.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: enh <enh@google.com>
Cc: Laurent Bercot <ska-dietlibc@skarnet.org>
Cc: Gabriel Ravier <gabravier@gmail.com>
Cc: Zack Weinberg <zack@owlfolio.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/Makefile.am
lib/fd.c [new file with mode: 0644]
lib/prototypes.h
src/chage.c
src/chfn.c
src/chsh.c
src/expiry.c
src/gpasswd.c
src/newgrp.c
src/passwd.c
src/su.c

index 7db960c8cd192fcfb257a1a1ba0b8f9f45c009bd..1146e39be9b3fb128f638e10091e4aa17eaeb9cf 100644 (file)
@@ -53,6 +53,7 @@ libshadow_la_SOURCES = \
        faillog.h \
        failure.c \
        failure.h \
+       fd.c \
        fields.c \
        find_new_gid.c \
        find_new_uid.c \
diff --git a/lib/fd.c b/lib/fd.c
new file mode 100644 (file)
index 0000000..bcfa374
--- /dev/null
+++ b/lib/fd.c
@@ -0,0 +1,41 @@
+// SPDX-FileCopyrightText: 2024, Skyler Ferrante <sjf5462@rit.edu>
+// SPDX-License-Identifier: BSD-3-Clause
+
+/**
+ * To protect against file descriptor omission attacks, we open the std file
+ * descriptors with /dev/null if they are not already open. Code is based on
+ * fix_fds from sudo.c.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "prototypes.h"
+
+static void check_fd(int fd);
+
+void
+check_fds(void)
+{
+       /**
+        * Make sure stdin, stdout, stderr are open
+        * If they are closed, set them to /dev/null
+        */
+       check_fd(STDIN_FILENO);
+       check_fd(STDOUT_FILENO);
+       check_fd(STDERR_FILENO);
+}
+
+static void
+check_fd(int fd)
+{
+       int  devnull;
+
+       if (fcntl(fd, F_GETFL, 0) != -1)
+               return;
+
+       devnull = open("/dev/null", O_RDWR);
+       if (devnull != fd)
+               abort();
+}
index cacf3d21c075288551b88e89b25966ee0b7c4856..b9d4fbdfe0a0d07dc27f18adbfe600cbff43c32f 100644 (file)
@@ -127,6 +127,9 @@ extern void initenv (void);
 extern void set_env (int, char *const *);
 extern void sanitize_env (void);
 
+/* fd.c */
+extern void check_fds (void);
+
 /* fields.c */
 extern void change_field (char *, size_t, const char *);
 extern int valid_field (const char *, const char *);
index b64961f69a53835d80d4afda6130e2ebfe8be1c0..18ad80eba0e5346f0b1ce4d942e0212c47e9ed66 100644 (file)
@@ -762,13 +762,12 @@ int main (int argc, char **argv)
        gid_t rgid;
        const struct passwd *pw;
 
-       /*
-        * Get the program name so that error messages can use it.
-        */
+       sanitize_env ();
+       check_fds ();
+
        log_set_progname(Prog);
        log_set_logfd(stderr);
 
-       sanitize_env ();
        (void) setlocale (LC_ALL, "");
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);
index 2fd81d3dcb8884c7b7dd3a08c44d7ead3a2bdc43..213b0bb79e4bf3b68ce2e9f491ee7a65c6f4ec6f 100644 (file)
@@ -616,10 +616,12 @@ int main (int argc, char **argv)
        char new_gecos[BUFSIZ]; /* buffer for new GECOS fields       */
        char *user;
 
+       sanitize_env ();
+       check_fds ();
+
        log_set_progname(Prog);
        log_set_logfd(stderr);
 
-       sanitize_env ();
        (void) setlocale (LC_ALL, "");
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);
index e29ac580e5e88a7cf7acdf6fd4577d13d7bbff95..c019e357e7fa5e43c82d452e389de1acb49b23b0 100644 (file)
@@ -473,6 +473,7 @@ int main (int argc, char **argv)
        const struct passwd *pw;        /* Password entry from /etc/passwd   */
 
        sanitize_env ();
+       check_fds ();
 
        log_set_progname(Prog);
        log_set_logfd(stderr);
index 673cbc3cbdb0c0e7d07b62ba6ce29e1780b68cca..1900335e4e4d7ce9d7f9388a5aecc369c9f82fc9 100644 (file)
@@ -123,11 +123,12 @@ int main (int argc, char **argv)
        struct passwd *pwd;
        struct spwd *spwd;
 
+       sanitize_env ();
+       check_fds ();
+
        log_set_progname(Prog);
        log_set_logfd(stderr);
 
-       sanitize_env ();
-
        /*
         * Start by disabling all of the keyboard signals.
         */
index 34205cc7846ef9e83de074e64f77fb0fa9776cb3..a3fa80d07146ef5ce16ec8ffc8f64dcbb7eb1af1 100644 (file)
@@ -956,6 +956,8 @@ int main (int argc, char **argv)
 #endif
 
        sanitize_env ();
+       check_fds ();
+
        (void) setlocale (LC_ALL, "");
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);
index 68e80fe9482078694c3a2a9f4fed6a25738c5a2a..051b5675cb347fa771edeff6e8f762f5c1bfc0fb 100644 (file)
@@ -390,6 +390,9 @@ int main (int argc, char **argv)
 #ifdef WITH_AUDIT
        audit_help_open ();
 #endif
+
+       check_fds ();
+
        (void) setlocale (LC_ALL, "");
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);
index 3ef0cf3feccabfc052487001407ffcd5f8c33ee7..b9873b06401d95b1727c100410836fd6a0a7ff1a 100644 (file)
@@ -730,6 +730,7 @@ int main (int argc, char **argv)
        const struct spwd *sp;  /* Shadow file entry for user   */
 
        sanitize_env ();
+       check_fds ();
 
        log_set_progname(Prog);
        log_set_logfd(stderr);
index 8c3be34601ad1b9c0c29390490888982c13109e0..f9a18e2599c13fc39a050393c9a1462ec87aec6b 100644 (file)
--- a/src/su.c
+++ b/src/su.c
@@ -999,6 +999,8 @@ int main (int argc, char **argv)
        int ret;
 #endif                         /* USE_PAM */
 
+       check_fds ();
+
        (void) setlocale (LC_ALL, "");
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);