Skip to content

Commit e6bbc83

Browse files
committed
MDEV-26212 PAM authentication fails with ENOMEM
use posix_spawn(), not fork() - it's better for systems that don't overcommit memory
1 parent d45841b commit e6bbc83

File tree

1 file changed

+32
-45
lines changed

1 file changed

+32
-45
lines changed

plugin/auth_pam/auth_pam.c

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <string.h>
2121
#include <sys/types.h>
2222
#include <sys/wait.h>
23+
#include <spawn.h>
2324
#include <mysql/plugin_auth.h>
2425
#include "auth_pam_tool.h"
2526
#include <my_global.h>
@@ -51,65 +52,51 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
5152
unsigned char field, *pkt;
5253
unsigned int n_sleep= 0;
5354
useconds_t sleep_time= 100;
55+
posix_spawn_file_actions_t file_actions;
56+
char toolpath[FN_REFLEN];
57+
size_t plugin_dir_len= strlen(opt_plugin_dir);
58+
char *const argv[2]= {toolpath, 0};
59+
int res;
5460

5561
PAM_DEBUG((stderr, "PAM: opening pipes.\n"));
5662
if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0)
5763
{
58-
/* Error creating pipes. */
64+
my_printf_error(ENOEXEC, "pam: cannot create pipes (errno: %M)",
65+
ME_ERROR_LOG_ONLY, errno);
5966
return CR_ERROR;
6067
}
61-
PAM_DEBUG((stderr, "PAM: forking.\n"));
62-
if ((proc_id= fork()) < 0)
63-
{
64-
/* Error forking. */
65-
close(p_to_c[0]);
66-
close(c_to_p[1]);
67-
goto error_ret;
68-
}
6968

70-
if (proc_id == 0)
69+
if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath))
7170
{
72-
/* The 'sandbox' process started. */
73-
char toolpath[FN_REFLEN];
74-
size_t plugin_dir_len= strlen(opt_plugin_dir);
75-
76-
PAM_DEBUG((stderr, "PAM: Child process prepares pipes.\n"));
77-
78-
if (close(p_to_c[1]) < 0 ||
79-
close(c_to_p[0]) < 0 ||
80-
dup2(p_to_c[0], 0) < 0 || /* Parent's pipe to STDIN. */
81-
dup2(c_to_p[1], 1) < 0) /* Sandbox's pipe to STDOUT. */
82-
{
83-
exit(-1);
84-
}
71+
my_printf_error(ENOEXEC, "pam: too long path to <plugindir>/%s",
72+
ME_ERROR_LOG_ONLY, tool_name);
73+
return CR_ERROR;
74+
}
8575

86-
PAM_DEBUG((stderr, "PAM: check tool directory: %s, %s.\n",
87-
opt_plugin_dir, tool_name));
88-
if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath))
89-
{
90-
/* Tool path too long. */
91-
exit(-1);
92-
}
76+
memcpy(toolpath, opt_plugin_dir, plugin_dir_len);
77+
if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR)
78+
toolpath[plugin_dir_len++]= FN_LIBCHAR;
79+
memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1);
9380

94-
memcpy(toolpath, opt_plugin_dir, plugin_dir_len);
95-
if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR)
96-
toolpath[plugin_dir_len++]= FN_LIBCHAR;
97-
memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1);
98-
99-
PAM_DEBUG((stderr, "PAM: execute pam sandbox [%s].\n", toolpath));
100-
(void) execl(toolpath, toolpath, NULL);
101-
PAM_DEBUG((stderr, "PAM: exec() failed.\n"));
102-
my_printf_error(1, "PAM: Cannot execute %s (errno: %M)", ME_ERROR_LOG_ONLY,
103-
toolpath, errno);
104-
exit(-1);
105-
}
81+
PAM_DEBUG((stderr, "PAM: forking %s\n", toolpath));
82+
res= posix_spawn_file_actions_init(&file_actions) ||
83+
posix_spawn_file_actions_addclose(&file_actions, p_to_c[1]) ||
84+
posix_spawn_file_actions_addclose(&file_actions, c_to_p[0]) ||
85+
posix_spawn_file_actions_adddup2(&file_actions, p_to_c[0], 0) ||
86+
posix_spawn_file_actions_adddup2(&file_actions, c_to_p[1], 1) ||
87+
posix_spawn(&proc_id, toolpath, &file_actions, NULL, argv, NULL);
10688

10789
/* Parent process continues. */
90+
posix_spawn_file_actions_destroy(&file_actions);
91+
close(p_to_c[0]);
92+
close(c_to_p[1]);
10893

109-
PAM_DEBUG((stderr, "PAM: parent continues.\n"));
110-
if (close(p_to_c[0]) < 0 ||
111-
close(c_to_p[1]) < 0)
94+
if (res)
95+
{
96+
my_printf_error(ENOEXEC, "pam: cannot exec %s (errno: %M)",
97+
ME_ERROR_LOG_ONLY, toolpath, errno);
11298
goto error_ret;
99+
}
113100

114101
/* no user name yet ? read the client handshake packet with the user name */
115102
if (info->user_name == 0)

0 commit comments

Comments
 (0)