Blob Blame History Raw
From e313bd648a4c8a9526421e270eb597a5de1e0c7f Mon Sep 17 00:00:00 2001
From: Lee Duncan <lduncan@suse.com>
Date: Fri, 15 Dec 2017 10:36:11 -0800
Subject: [PATCH] Check for root peer user for iscsiuio IPC

This fixes a possible vulnerability where a non-root
process could connect with iscsiuio. Fouund by Qualsys.
---
 iscsiuio/src/unix/Makefile.am  |  3 ++-
 iscsiuio/src/unix/iscsid_ipc.c | 47 ++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/iscsiuio/src/unix/Makefile.am b/iscsiuio/src/unix/Makefile.am
index 71d54633a764..a989ef029b59 100644
--- a/iscsiuio/src/unix/Makefile.am
+++ b/iscsiuio/src/unix/Makefile.am
@@ -20,7 +20,8 @@ iscsiuio_SOURCES =	build_date.c		\
 			nic_utils.c		\
 			packet.c		\
 			iscsid_ipc.c		\
-			ping.c
+			ping.c			\
+			${top_srcdir}/../utils/sysdeps/sysdeps.c
 
 iscsiuio_CFLAGS = 	$(AM_CFLAGS)		\
 			$(LIBNL_CFLAGS)		\
diff --git a/iscsiuio/src/unix/iscsid_ipc.c b/iscsiuio/src/unix/iscsid_ipc.c
index 658362899234..64762654c523 100644
--- a/iscsiuio/src/unix/iscsid_ipc.c
+++ b/iscsiuio/src/unix/iscsid_ipc.c
@@ -37,6 +37,8 @@
  *
  */
 
+#define _GNU_SOURCE
+
 #include <errno.h>
 #include <pthread.h>
 #include <signal.h>
@@ -47,6 +49,8 @@
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/un.h>
+#include <sys/types.h>
+#include <pwd.h>
 
 #define PFX "iscsi_ipc "
 
@@ -61,6 +65,7 @@
 #include "iscsid_ipc.h"
 #include "uip.h"
 #include "uip_mgmt_ipc.h"
+#include "sysdeps.h"
 
 #include "logger.h"
 #include "uip.h"
@@ -102,6 +107,7 @@ struct iface_rec_decode {
 	uint16_t		mtu;
 };
 
+#define PEERUSER_MAX	64
 
 /******************************************************************************
  *  Globals
@@ -1024,6 +1030,40 @@ static void iscsid_loop_close(void *arg)
 	LOG_INFO(PFX "iSCSI daemon socket closed");
 }
 
+/*
+ * check that the peer user is privilidged
+ *
+ * return 1 if peer is ok else 0
+ *
+ * XXX: this function is copied from iscsid_ipc.c and should be
+ * moved into a common library
+ */
+static int
+mgmt_peeruser(int sock, char *user)
+{
+	struct ucred peercred;
+	socklen_t so_len = sizeof(peercred);
+	struct passwd *pass;
+
+	errno = 0;
+	if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred,
+		&so_len) != 0 || so_len != sizeof(peercred)) {
+		/* We didn't get a valid credentials struct. */
+		LOG_ERR(PFX "peeruser_unux: error receiving credentials: %m");
+		return 0;
+	}
+
+	pass = getpwuid(peercred.uid);
+	if (pass == NULL) {
+		LOG_ERR(PFX "peeruser_unix: unknown local user with uid %d",
+				(int) peercred.uid);
+		return 0;
+	}
+
+	strlcpy(user, pass->pw_name, PEERUSER_MAX);
+	return 1;
+}
+
 /**
  *  iscsid_loop() - This is the function which will process the broadcast
  *                  messages from iscsid
@@ -1033,6 +1073,7 @@ static void *iscsid_loop(void *arg)
 {
 	int rc;
 	sigset_t set;
+	char user[PEERUSER_MAX];
 
 	pthread_cleanup_push(iscsid_loop_close, arg);
 
@@ -1072,6 +1113,12 @@ static void *iscsid_loop(void *arg)
 			continue;
 		}
 
+		if (!mgmt_peeruser(iscsid_opts.fd, user) || strncmp(user, "root", PEERUSER_MAX)) {
+			close(s2);
+			LOG_ERR(PFX "Access error: non-administrative connection rejected");
+			break;
+		}
+
 		process_iscsid_broadcast(s2);
 		close(s2);
 	}
-- 
2.17.2