diff --git a/Makefile.in b/Makefile.in index 5c1f8379c..dc3160462 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,6 +84,7 @@ install_system_dirs: $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR) $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR) $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR) + $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR) $(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache install_initscripts: diff --git a/VERSION b/VERSION index 517a4a6f0..d8a82298a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.02.71(2)-cvs (2010-07-28) +2.02.72(2)-cvs (2010-07-28) diff --git a/WHATS_NEW b/WHATS_NEW index 5272d77d7..f6487ff71 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,3 +1,9 @@ +Version 2.02.72 - 28th July 2010 [CVE-2010-2526] +================================================= + Change clvmd to communicate with lvm2 via a socket in /var/run/lvm. + Return controlled error if clvmd is run by non-root user. + Add configure --default-run-dir for /var/run/lvm. + Version 2.02.71 - 28th July 2010 ================================ Document LVM fault handling in doc/lvm_fault_handling.txt. diff --git a/configure b/configure index a51104de2..056c6dbbc 100755 --- a/configure +++ b/configure @@ -863,6 +863,7 @@ with_udev_prefix with_udevdir with_dmeventd_pidfile with_dmeventd_path +with_default_run_dir with_default_system_dir with_default_archive_subdir with_default_backup_subdir @@ -1599,6 +1600,7 @@ Optional Packages: dmeventd pidfile [/var/run/dmeventd.pid] --with-dmeventd-path=PATH dmeventd path [EPREFIX/sbin/dmeventd] + --with-default-run-dir=DIR Default run directory [/var/run/lvm] --with-default-system-dir=DIR default LVM system directory [/etc/lvm] --with-default-archive-subdir=SUBDIR @@ -17816,6 +17818,21 @@ _ACEOF fi + + + +# Check whether --with-default-run-dir was given. +if test "${with_default_run_dir+set}" = set; then + withval=$with_default_run_dir; DEFAULT_RUN_DIR="$withval" +else + DEFAULT_RUN_DIR="/var/run/lvm" +fi + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_RUN_DIR "$DEFAULT_RUN_DIR" +_ACEOF + + ################################################################################ # Check whether --with-default-system-dir was given. diff --git a/configure.in b/configure.in index 2b1987b2b..bd5613636 100644 --- a/configure.in +++ b/configure.in @@ -1127,6 +1127,13 @@ if test "$BUILD_DMEVENTD" = yes; then [Path to dmeventd binary.]) fi +AH_TEMPLATE(DEFAULT_RUN_DIR, [Name of default run directory.]) +AC_ARG_WITH(default-run-dir, + [ --with-default-run-dir=DIR Default run directory [[/var/run/lvm]] ], + [ DEFAULT_RUN_DIR="$withval" ], + [ DEFAULT_RUN_DIR="/var/run/lvm" ]) +AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR,["$DEFAULT_RUN_DIR"] ) + ################################################################################ dnl -- various defaults AC_ARG_WITH(default-system-dir, diff --git a/daemons/clvmd/clvm.h b/daemons/clvmd/clvm.h index 92f807f72..c9ea10c49 100644 --- a/daemons/clvmd/clvm.h +++ b/daemons/clvmd/clvm.h @@ -22,6 +22,8 @@ #ifndef _CLVM_H #define _CLVM_H +#include "configure.h" + struct clvm_header { uint8_t cmd; /* See below */ uint8_t flags; /* See below */ @@ -45,9 +47,8 @@ struct clvm_header { #define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */ #define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */ -/* Name of the local socket to communicate between libclvm and clvmd */ -//static const char CLVMD_SOCKNAME[]="/var/run/clvmd"; -static const char CLVMD_SOCKNAME[] = "\0clvmd"; +/* Name of the local socket to communicate between lvm and clvmd */ +static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock"; /* Internal commands & replies */ #define CLVMD_CMD_REPLY 1 diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c index 4f5ed977c..2365a3310 100644 --- a/daemons/clvmd/clvmd.c +++ b/daemons/clvmd/clvmd.c @@ -123,6 +123,7 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd, static int process_reply(const struct clvm_header *msg, int msglen, const char *csid); static int open_local_sock(void); +static void close_local_sock(int local_socket); static int check_local_clvmd(void); static struct local_client *find_client(int clientid); static void main_loop(int local_sock, int cmd_timeout); @@ -276,6 +277,23 @@ static void remove_lockfile(void) unlink(CLVMD_PIDFILE); } +/* + * clvmd require dm-ioctl capability for operation + */ +static void check_permissions() +{ + if (getuid() || geteuid()) { + log_error("Cannot run as a non-root user."); + + /* + * Fail cleanly here if not run as root, instead of failing + * later when attempting a root-only operation + * Preferred exit code from an initscript for this. + */ + exit(4); + } +} + int main(int argc, char *argv[]) { int local_sock; @@ -305,9 +323,11 @@ int main(int argc, char *argv[]) exit(0); case 'R': + check_permissions(); return refresh_clvmd(1)==1?0:1; case 'S': + check_permissions(); return restart_clvmd(clusterwide_opt)==1?0:1; case 'C': @@ -353,6 +373,8 @@ int main(int argc, char *argv[]) } } + check_permissions(); + /* Setting debug options on an existing clvmd */ if (debug_opt && !check_local_clvmd()) { @@ -521,6 +543,7 @@ int main(int argc, char *argv[]) /* Do some work */ main_loop(local_sock, cmd_timeout); + close_local_sock(local_sock); destroy_lvm(); return 0; @@ -864,7 +887,6 @@ static void main_loop(int local_sock, int cmd_timeout) closedown: clops->cluster_closedown(); - close(local_sock); } static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout) @@ -1963,20 +1985,30 @@ static int check_local_clvmd(void) return ret; } +static void close_local_sock(int local_socket) +{ + if (local_socket != -1 && close(local_socket)) + stack; + + if (CLVMD_SOCKNAME[0] != '\0' && unlink(CLVMD_SOCKNAME)) + stack; +} /* Open the local socket, that's the one we talk to libclvm down */ static int open_local_sock() { - int local_socket; + int local_socket = -1; struct sockaddr_un sockaddr; + mode_t old_mask; + + close_local_sock(local_socket); + old_mask = umask(0077); /* Open local socket */ - if (CLVMD_SOCKNAME[0] != '\0') - unlink(CLVMD_SOCKNAME); local_socket = socket(PF_UNIX, SOCK_STREAM, 0); if (local_socket < 0) { log_error("Can't create local socket: %m"); - return -1; + goto error; } /* Set Close-on-exec & non-blocking */ @@ -1989,18 +2021,19 @@ static int open_local_sock() sockaddr.sun_family = AF_UNIX; if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) { log_error("can't bind local socket: %m"); - close(local_socket); - return -1; + goto error; } if (listen(local_socket, 1) != 0) { log_error("listen local: %m"); - close(local_socket); - return -1; + goto error; } - if (CLVMD_SOCKNAME[0] != '\0') - chmod(CLVMD_SOCKNAME, 0600); + umask(old_mask); return local_socket; +error: + close_local_sock(local_socket); + umask(old_mask); + return -1; } void process_message(struct local_client *client, const char *buf, int len, diff --git a/daemons/clvmd/clvmd.h b/daemons/clvmd/clvmd.h index aec31b2c9..ccc79cc34 100644 --- a/daemons/clvmd/clvmd.h +++ b/daemons/clvmd/clvmd.h @@ -20,9 +20,6 @@ #define CLVMD_MINOR_VERSION 2 #define CLVMD_PATCH_VERSION 1 -/* Name of the cluster LVM admin lock */ -#define ADMIN_LOCK_NAME "CLVMD_ADMIN" - /* Default time (in seconds) we will wait for all remote commands to execute before declaring them dead */ #define DEFAULT_CMD_TIMEOUT 60 diff --git a/lib/misc/configure.h.in b/lib/misc/configure.h.in index 01f668cef..3a3767895 100644 --- a/lib/misc/configure.h.in +++ b/lib/misc/configure.h.in @@ -35,6 +35,9 @@ /* Name of default locking directory. */ #undef DEFAULT_LOCK_DIR +/* Name of default run directory. */ +#undef DEFAULT_RUN_DIR + /* Define to 0 to reinstate the pre-2.02.54 handling of unit suffixes. */ #undef DEFAULT_SI_UNIT_CONSISTENCY