pam_namespace: protect_dir(): use O_DIRECTORY to prevent local DoS situations 14/311114/1 accepted/tizen_base accepted/tizen_base_toolchain accepted/tizen_base_x accepted/tizen_base_x_asan tizen_base accepted/tizen/base/20240530.091900 accepted/tizen/base/toolchain/20240603.231421 accepted/tizen/base/x/20240526.035713 accepted/tizen/base/x/asan/20240624.231401
authorMatthias Gerstner <matthias.gerstner@suse.de>
Wed, 27 Dec 2023 13:01:59 +0000 (14:01 +0100)
committeryoungjae cho <y0.cho@samsung.com>
Tue, 14 May 2024 07:56:21 +0000 (07:56 +0000)
(backporting, CVE-2024-22356)

Without O_DIRECTORY the path crawling logic is subject to e.g. FIFOs
being placed in user controlled directories, causing the PAM module to
block indefinitely during `openat()`.

Pass O_DIRECTORY to cause the `openat()` to fail if the path does not
refer to a directory.

With this the check whether the final path element is a directory
becomes unnecessary, drop it.

Original: upstream, https://github.com/linux-pam/linux-pam/commit/031bb5a
Change-Id: I099e6d7fa62446160babf79d41fb19bfbfe5b186
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
(cherry picked from commit cb1ff0632d1d392606509c46d8fd25271a715825)

modules/pam_namespace/pam_namespace.c

index a40f05e..ed9b5fd 100644 (file)
@@ -1012,7 +1012,7 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
        int dfd = AT_FDCWD;
        int dfd_next;
        int save_errno;
-       int flags = O_RDONLY;
+       int flags = O_RDONLY | O_DIRECTORY;
        int rv = -1;
        struct stat st;
 
@@ -1066,22 +1066,6 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
                rv = openat(dfd, dir, flags);
        }
 
-       if (rv != -1) {
-               if (fstat(rv, &st) != 0) {
-                       save_errno = errno;
-                       close(rv);
-                       rv = -1;
-                       errno = save_errno;
-                       goto error;
-               }
-               if (!S_ISDIR(st.st_mode)) {
-                       close(rv);
-                       errno = ENOTDIR;
-                       rv = -1;
-                       goto error;
-               }
-       }
-
        if (flags & O_NOFOLLOW) {
                /* we are inside user-owned dir - protect */
                if (protect_mount(rv, p, idata) == -1) {