Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-26212

PAM authentication fails with ENOMEM

Details

    Description

      When using the authentication plugin PAM it fails in case the mariadb process uses more memory than is still free and memory overcommit is disabled.

      The reason lies in fork() (https://github.com/MariaDB/server/blob/10.7/plugin/auth_pam/auth_pam.c#L62) which duplicates the process. As there is not enough free memory for a duplicate process fork() fails (silently) and the authentication does not succeed.

      As the forked process is only used to exec() the pam tool, there is no need for a fork of the whole server process.

      It can be reproduced by running a mariadb server with an innodb_buffer of more than half of the server's (best a VM with as few RAM as possible) RAM and filling it up by selecting a big table of test data.

      This issue had already been reported in Percona server: https://jira.percona.com/browse/PS-3332

      Cheers
      Volker

      Attachments

        Issue Links

          Activity

            https://jira.percona.com/browse/PS-3332 was closed with "Cannot Reproduce".

            fork() does not duplicate the whole process memory, that would be too slow to be practically usable. It only copies changed pages, so if one of the processes rewrites the whole of innodb buffer pool — it'll be duplicated, yes. But the child process calls exec() immediately after the fork(). The parent cannot do much in that short time frame.

            serg Sergei Golubchik added a comment - https://jira.percona.com/browse/PS-3332 was closed with "Cannot Reproduce". fork() does not duplicate the whole process memory, that would be too slow to be practically usable. It only copies changed pages, so if one of the processes rewrites the whole of innodb buffer pool — it'll be duplicated, yes. But the child process calls exec() immediately after the fork() . The parent cannot do much in that short time frame.
            vklasen Volker Klasen added a comment - - edited

            fork() does not duplicate the memory, but it kind of reserves it. Without overcommit this will be too much for big mariadb processes. I found a post which describes the issue quite good:

            https://mail.gnome.org/archives/gtk-devel-list/2018-April/msg00000.html

            When gnome-shell is launching apps (via glib) it ultimately comes down
            to fork() + exec(). In this case the fork() fails with ENOMEM, because
            the Linux kernel worries that the process being forked may end up
            duplicating all of the memory allocations of the shell. By default the
            memory map is set up so that the new process has a view on the exact
            same pages as the parent process, however they are set up as
            copy-on-write, so if the child writes to such memory it'll silently
            cause new memory to be allocated. Under that limited perspective, the
            kernel is not totally out of line in worrying about this situation,
            especially because gnome-shell is a RAM-heavy process.

            In reality we only want to fork() to immediately exec() which replaces
            the child process memory map with a blank slate, but this
            misinterpretation of intentions is a limitation of the fork() API
            combined with a conflict with Linux's memory overcommit model.

            vklasen Volker Klasen added a comment - - edited fork() does not duplicate the memory, but it kind of reserves it. Without overcommit this will be too much for big mariadb processes. I found a post which describes the issue quite good: https://mail.gnome.org/archives/gtk-devel-list/2018-April/msg00000.html When gnome-shell is launching apps (via glib) it ultimately comes down to fork() + exec(). In this case the fork() fails with ENOMEM, because the Linux kernel worries that the process being forked may end up duplicating all of the memory allocations of the shell. By default the memory map is set up so that the new process has a view on the exact same pages as the parent process, however they are set up as copy-on-write, so if the child writes to such memory it'll silently cause new memory to be allocated. Under that limited perspective, the kernel is not totally out of line in worrying about this situation, especially because gnome-shell is a RAM-heavy process. In reality we only want to fork() to immediately exec() which replaces the child process memory map with a blank slate, but this misinterpretation of intentions is a limitation of the fork() API combined with a conflict with Linux's memory overcommit model.
            vklasen Volker Klasen added a comment -

            I attached a patch that replaces fork() + exec() by posix_spawn() with which I could no longer reproduce the bug and could login via PAM even when the server process used more than 50% of available RAM.
            However, as I am not very familiar with C, memory management and such, I cannot rule out side effects.

            Cheers
            Volker

            vklasen Volker Klasen added a comment - I attached a patch that replaces fork() + exec() by posix_spawn() with which I could no longer reproduce the bug and could login via PAM even when the server process used more than 50% of available RAM. However, as I am not very familiar with C, memory management and such, I cannot rule out side effects. Cheers Volker

            Thanks. I've replaced fork() + exec() with posix_spawn()

            serg Sergei Golubchik added a comment - Thanks. I've replaced fork() + exec() with posix_spawn()

            People

              serg Sergei Golubchik
              vklasen Volker Klasen
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.