File fix_security_issue_in_clvmd.diff of Package lvm2
Index: LVM2.2.02.39/daemons/clvmd/clvm.h
===================================================================
--- LVM2.2.02.39.orig/daemons/clvmd/clvm.h 2010-08-10 11:32:27.000000000 +0800
+++ LVM2.2.02.39/daemons/clvmd/clvm.h 2010-08-10 11:34:28.000000000 +0800
@@ -47,7 +47,8 @@
/* 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";
+#define CLVMD_SOCKDIR "/var/run/lvm"
+static const char CLVMD_SOCKNAME[] = CLVMD_SOCKDIR"/clvmd.sock";
/* Internal commands & replies */
#define CLVMD_CMD_REPLY 1
Index: LVM2.2.02.39/daemons/clvmd/clvmd.c
===================================================================
--- LVM2.2.02.39.orig/daemons/clvmd/clvmd.c 2010-08-10 11:32:27.000000000 +0800
+++ LVM2.2.02.39/daemons/clvmd/clvmd.c 2010-08-10 11:34:28.000000000 +0800
@@ -125,6 +125,7 @@
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);
@@ -247,6 +248,22 @@
return buf;
}
+/*
+ * 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;
@@ -274,6 +291,7 @@
exit(0);
case 'R':
+ check_permissions();
return refresh_clvmd();
case 'C':
@@ -316,6 +334,8 @@
}
}
+ check_permissions();
+
/* Setting debug options on an existing clvmd */
if (debug_opt && !check_local_clvmd()) {
@@ -440,6 +460,7 @@
/* Do some work */
main_loop(local_sock, cmd_timeout);
+ close_local_sock(local_sock);
return 0;
}
@@ -772,7 +793,6 @@
closedown:
clops->cluster_closedown();
- close(local_sock);
}
static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
@@ -1867,20 +1887,41 @@
return ret;
}
+static void close_local_sock(int local_socket)
+{
+ int res;
+ if (local_socket != -1 && close(local_socket))
+ stack;
+ if (local_socket == -1) {
+ res = access(CLVMD_SOCKDIR, R_OK|W_OK|X_OK);
+ if (res == -1) {
+ if (errno == ENOENT)
+ mkdir(CLVMD_SOCKDIR, 0700);
+ else if (errno == EACCES)
+ chmod(CLVMD_SOCKDIR, 0700);
+ else
+ 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 */
fcntl(local_socket, F_SETFD, 1);
@@ -1891,18 +1932,19 @@
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,