mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +03:00
lvmlockctl: replace popen and system
with fork and exec to avoid use of shell. largely copied from lib/misc/lvm-exec.c require lvmlockctl_kill_command to be full path use lvm config instead of lvmconfig to avoid need for LVM_DIR
This commit is contained in:
parent
89a3440fc0
commit
f5fbb1b76f
3
configure
vendored
3
configure
vendored
@ -693,7 +693,6 @@ MANGLING
|
|||||||
LVM_RELEASE_DATE
|
LVM_RELEASE_DATE
|
||||||
LVM_RELEASE
|
LVM_RELEASE
|
||||||
LVM_PATH
|
LVM_PATH
|
||||||
LVM_DIR
|
|
||||||
LVM_PATCHLEVEL
|
LVM_PATCHLEVEL
|
||||||
LVM_MINOR
|
LVM_MINOR
|
||||||
LVM_MAJOR
|
LVM_MAJOR
|
||||||
@ -13767,11 +13766,9 @@ SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
|||||||
|
|
||||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||||
LVM_PATH="$SBINDIR/lvm"
|
LVM_PATH="$SBINDIR/lvm"
|
||||||
LVM_DIR="$SBINDIR/"
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define LVM_PATH "$LVM_PATH"
|
#define LVM_PATH "$LVM_PATH"
|
||||||
#define LVM_DIR "$LVM_DIR"
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
|
||||||
|
@ -1607,9 +1607,7 @@ SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
|||||||
|
|
||||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||||
LVM_PATH="$SBINDIR/lvm"
|
LVM_PATH="$SBINDIR/lvm"
|
||||||
LVM_DIR="$SBINDIR/"
|
|
||||||
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
||||||
AC_DEFINE_UNQUOTED(LVM_DIR, ["$LVM_DIR"], [Path to lvm binary dir.])
|
|
||||||
|
|
||||||
LVMCONFIG_PATH="$SBINDIR/lvmconfig"
|
LVMCONFIG_PATH="$SBINDIR/lvmconfig"
|
||||||
AC_DEFINE_UNQUOTED(LVMCONFIG_PATH, ["$LVMCONFIG_PATH"], [Path to lvmconfig binary.])
|
AC_DEFINE_UNQUOTED(LVMCONFIG_PATH, ["$LVMCONFIG_PATH"], [Path to lvmconfig binary.])
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
static int quit = 0;
|
static int quit = 0;
|
||||||
static int info = 0;
|
static int info = 0;
|
||||||
@ -519,24 +522,224 @@ static int do_stop_lockspaces(void)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _reopen_fd_to_null(int fd)
|
||||||
|
{
|
||||||
|
int null_fd;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
|
||||||
|
log_error("open error /dev/null %d", errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(fd)) {
|
||||||
|
log_error("close error fd %d %d", fd, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dup2(null_fd, fd) == -1) {
|
||||||
|
log_error("dup2 error %d", errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
out:
|
||||||
|
if (close(null_fd)) {
|
||||||
|
log_error("close error fd %d %d", null_fd, errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_AV_COUNT 32
|
||||||
|
#define ONE_ARG_LEN 1024
|
||||||
|
|
||||||
|
static void _run_command_pipe(const char *cmd_str, pid_t *pid_out, FILE **fp_out)
|
||||||
|
{
|
||||||
|
char arg[ONE_ARG_LEN];
|
||||||
|
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
|
||||||
|
char *arg_dup;
|
||||||
|
int av_count = 0;
|
||||||
|
int cmd_len;
|
||||||
|
int arg_len;
|
||||||
|
pid_t pid = 0;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int pipefd[2];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||||
|
av[i] = NULL;
|
||||||
|
|
||||||
|
cmd_len = strlen(cmd_str);
|
||||||
|
|
||||||
|
memset(&arg, 0, sizeof(arg));
|
||||||
|
arg_len = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < cmd_len; i++) {
|
||||||
|
if (!cmd_str[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (av_count == MAX_AV_COUNT)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (cmd_str[i] == '\\') {
|
||||||
|
if (i == (cmd_len - 1))
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (cmd_str[i] == '\\') {
|
||||||
|
arg[arg_len++] = cmd_str[i];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isspace(cmd_str[i])) {
|
||||||
|
arg[arg_len++] = cmd_str[i];
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
|
||||||
|
arg[arg_len++] = cmd_str[i];
|
||||||
|
} else if (isspace(cmd_str[i])) {
|
||||||
|
if (arg_len) {
|
||||||
|
if (!(arg_dup = strdup(arg)))
|
||||||
|
goto out;
|
||||||
|
av[av_count++] = arg_dup;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(arg, 0, sizeof(arg));
|
||||||
|
arg_len = 0;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_len) {
|
||||||
|
if (av_count >= MAX_AV_COUNT)
|
||||||
|
goto out;
|
||||||
|
if (!(arg_dup = strdup(arg)))
|
||||||
|
goto out;
|
||||||
|
av[av_count++] = arg_dup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe(pipefd)) {
|
||||||
|
log_error("pipe error %d", errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if (pid < 0) {
|
||||||
|
log_error("fork error %d", errno);
|
||||||
|
pid = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
/* Child -> writer, convert pipe[0] to STDOUT */
|
||||||
|
if (!_reopen_fd_to_null(STDIN_FILENO))
|
||||||
|
log_error("reopen STDIN error");
|
||||||
|
else if (close(pipefd[0 /*read*/]))
|
||||||
|
log_error("close error pipe[0] %d", errno);
|
||||||
|
else if (close(STDOUT_FILENO))
|
||||||
|
log_error("close error STDOUT %d", errno);
|
||||||
|
else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1)
|
||||||
|
log_error("dup2 error STDOUT %d", errno);
|
||||||
|
else if (close(pipefd[1]))
|
||||||
|
log_error("close error pipe[1] %d", errno);
|
||||||
|
else {
|
||||||
|
execvp(av[0], av);
|
||||||
|
log_error("execvp error %d", errno);
|
||||||
|
}
|
||||||
|
_exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parent -> reader */
|
||||||
|
if (close(pipefd[1 /*write*/]))
|
||||||
|
log_error("close error STDOUT %d", errno);
|
||||||
|
|
||||||
|
if (!(fp = fdopen(pipefd[0 /*read*/], "r"))) {
|
||||||
|
log_error("fdopen STDIN error %d", errno);
|
||||||
|
if (close(pipefd[0]))
|
||||||
|
log_error("close error STDIN %d", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||||
|
free(av[i]);
|
||||||
|
|
||||||
|
*pid_out = pid;
|
||||||
|
*fp_out = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns -1 on error, 0 on success. */
|
||||||
|
|
||||||
|
static int _close_command_pipe(pid_t pid, FILE *fp)
|
||||||
|
{
|
||||||
|
int status, estatus;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (waitpid(pid, &status, 0) != pid) {
|
||||||
|
log_error("waitpid error pid %d %d", pid, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
/* pid exited with an exit code */
|
||||||
|
estatus = WEXITSTATUS(status);
|
||||||
|
|
||||||
|
/* exit status 0: child success */
|
||||||
|
if (!estatus) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exit status not zero: child error */
|
||||||
|
log_error("child exit error %d", estatus);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
/* pid terminated due to a signal */
|
||||||
|
log_error("child exit from signal");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error("child exit problem");
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fp && fclose(fp))
|
||||||
|
log_error("fclose error STDIN %d", errno);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns -1 on error, 0 on success. */
|
/* Returns -1 on error, 0 on success. */
|
||||||
|
|
||||||
static int _get_kill_command(char *kill_cmd)
|
static int _get_kill_command(char *kill_cmd)
|
||||||
{
|
{
|
||||||
char config_cmd[PATH_MAX] = { 0 };
|
char config_cmd[PATH_MAX + 128] = { 0 };
|
||||||
char config_val[1024] = { 0 };
|
char config_val[1024] = { 0 };
|
||||||
char line[PATH_MAX] = { 0 };
|
char line[PATH_MAX] = { 0 };
|
||||||
char type[4] = { 0 };
|
pid_t pid = 0;
|
||||||
FILE *fp;
|
FILE *fp = NULL;
|
||||||
|
|
||||||
snprintf(config_cmd, PATH_MAX, "%s/lvmconfig --typeconfig full global/lvmlockctl_kill_command", LVM_DIR);
|
snprintf(config_cmd, PATH_MAX, "%s config --typeconfig full global/lvmlockctl_kill_command", LVM_PATH);
|
||||||
type[0] = 'r';
|
|
||||||
|
|
||||||
if (!(fp = popen(config_cmd, type))) {
|
_run_command_pipe(config_cmd, &pid, &fp);
|
||||||
|
|
||||||
|
if (!pid) {
|
||||||
log_error("failed to run %s", config_cmd);
|
log_error("failed to run %s", config_cmd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
log_error("failed to get output %s", config_cmd);
|
||||||
|
_close_command_pipe(pid, fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fgets(line, sizeof(line), fp)) {
|
if (!fgets(line, sizeof(line), fp)) {
|
||||||
log_error("no output from %s", config_cmd);
|
log_error("no output from %s", config_cmd);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -552,14 +755,20 @@ static int _get_kill_command(char *kill_cmd)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config_val[0] != '/') {
|
||||||
|
log_error("lvmlockctl_kill_command must be full path");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
printf("Found lvmlockctl_kill_command: %s\n", config_val);
|
printf("Found lvmlockctl_kill_command: %s\n", config_val);
|
||||||
|
|
||||||
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
|
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
|
||||||
|
kill_cmd[PATH_MAX-1] = '\0';
|
||||||
|
|
||||||
pclose(fp);
|
_close_command_pipe(pid, fp);
|
||||||
return 0;
|
return 0;
|
||||||
bad:
|
bad:
|
||||||
pclose(fp);
|
_close_command_pipe(pid, fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,14 +776,20 @@ bad:
|
|||||||
|
|
||||||
static int _run_kill_command(char *kill_cmd)
|
static int _run_kill_command(char *kill_cmd)
|
||||||
{
|
{
|
||||||
int status;
|
pid_t pid = 0;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int rv;
|
||||||
|
|
||||||
status = system(kill_cmd);
|
_run_command_pipe(kill_cmd, &pid, &fp);
|
||||||
|
rv = _close_command_pipe(pid, fp);
|
||||||
if (!WEXITSTATUS(status))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
if (!pid)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (rv < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_drop(void)
|
static int do_drop(void)
|
||||||
|
@ -586,9 +586,6 @@
|
|||||||
/* Path to lvm binary. */
|
/* Path to lvm binary. */
|
||||||
#undef LVM_PATH
|
#undef LVM_PATH
|
||||||
|
|
||||||
/* Path to lvm binary dir. */
|
|
||||||
#undef LVM_DIR
|
|
||||||
|
|
||||||
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
|
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
|
||||||
*/
|
*/
|
||||||
#undef MAJOR_IN_MKDEV
|
#undef MAJOR_IN_MKDEV
|
||||||
|
Loading…
Reference in New Issue
Block a user