All of lore.kernel.org
 help / color / mirror / Atom feed
* RFC - Display context information using iproute2 ss utility
@ 2014-02-07 16:22 Richard Haines
  2014-02-07 17:03 ` Ole Kliemann
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Haines @ 2014-02-07 16:22 UTC (permalink / raw)
  To: selinux list

[-- Attachment #1: Type: text/plain, Size: 649 bytes --]

I've been patching the iproute2 "ss" utility to display the SELinux
security contexts for process and sockets, however I'm not sure
whether the socket contexts are correct (I expected most to show
system_u:object_r:....). 

I'm taking the socket contexts from /proc/PID/fd as was mentioned in
a previous email regarding socket contexts - is this correct ??

I've attached the patch that is built against:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git

Also is it possible to obtain a sockets peer context from userspace
using the /proc/PID/fd information as it would be useful to show this.

Richard

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ss-Add-support-for-retrieving-SELinux-contexts.patch --]
[-- Type: text/x-patch; name="0001-ss-Add-support-for-retrieving-SELinux-contexts.patch", Size: 13635 bytes --]

From 7d61b9f9e5098a594305364e1380c492eef52091 Mon Sep 17 00:00:00 2001
From: Richard Haines <richard_c_haines@btinternet.com>
Date: Fri, 7 Feb 2014 15:02:53 +0000
Subject: [PATCH] ss: Add support for retrieving SELinux contexts

The SELinux contexts can be added to the output using the -Z option.
The process and socket contexts are retrieved but for netlink sockets:
if valid process show process context, if pid = 0 show kernel initial
context, if unknown show "not available".

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
 configure     |  16 +++++
 man/man8/ss.8 |  19 ++++++
 misc/Makefile |  12 ++++
 misc/ss.c     | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 235 insertions(+), 21 deletions(-)

diff --git a/configure b/configure
index da01c19..854837e 100755
--- a/configure
+++ b/configure
@@ -231,6 +231,19 @@ EOF
     rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest
 }
 
+check_selinux()
+# SELinux is a compile time option in the ss utility
+{
+	SELINUX_LIB=$(${PKG_CONFIG} --silence-errors libselinux --libs)
+	if [ -n "$SELINUX_LIB" ]
+	then
+	echo "HAVE_SELINUX:=y" >>Config
+	echo "yes"
+    else
+	echo "no"
+	fi
+}
+
 echo "# Generated config based on" $INCLUDE >Config
 check_toolchain
 
@@ -253,3 +266,6 @@ check_ipt_lib_dir
 
 echo -n "libc has setns: "
 check_setns
+
+echo -n "SELinux support: "
+check_selinux
diff --git a/man/man8/ss.8 b/man/man8/ss.8
index 807d9dc..2fbed36 100644
--- a/man/man8/ss.8
+++ b/man/man8/ss.8
@@ -53,6 +53,22 @@ Print summary statistics. This option does not parse socket lists obtaining
 summary from various sources. It is useful when amount of sockets is so huge
 that parsing /proc/net/tcp is painful.
 .TP
+.B \-Z, \-\-context
+Show SELinux security contexts. Both the process and socket contexts will
+be displayed (for those with socket file descriptors). For 
+.BR netlink (7)
+sockets, the context displayed is as follows:
+.RS
+.RS
+.IP "1." 4
+If a valid process show pid context.
+.IP "2." 4
+If destination is kernel (pid = 0) show kernel initial context.
+.IP "3." 4
+If allocated by the kernel or netlink user show context as "not available".
+.RE
+.RE
+.TP
 .B \-b, \-\-bpf
 Show socket BPF filters (only administrators are allowed to get these information).
 .TP
@@ -103,6 +119,9 @@ Please take a look at the official documentation (Debian package iproute-doc) fo
 .B ss -t -a
 Display all TCP sockets.
 .TP
+.B ss -t -a -Z
+Display all TCP sockets with process and socket SELinux security contexts.
+.TP
 .B ss -u -a
 Display all UDP sockets.
 .TP
diff --git a/misc/Makefile b/misc/Makefile
index a59ff87..a946a85 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -8,6 +8,18 @@ include ../Config
 all: $(TARGETS)
 
 ss: $(SSOBJ)
+ifeq ($(HAVE_SELINUX),y)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SSOBJ) $(LDLIBS) -lselinux
+else
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SSOBJ) $(LDLIBS)
+endif
+
+ss.o: ss.c
+ifeq ($(HAVE_SELINUX),y)
+	$(CC) $(CFLAGS) -DHAVE_SELINUX -c $+
+else
+	$(CC) $(CFLAGS) -c $+
+endif
 
 nstat: nstat.c
 	$(CC) $(CFLAGS) $(LDFLAGS) -o nstat nstat.c -lm
diff --git a/misc/ss.c b/misc/ss.c
index 764ffe2..1e1d3fb 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -40,6 +40,9 @@
 #include <linux/filter.h>
 #include <linux/packet_diag.h>
 #include <linux/netlink_diag.h>
+#if HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
 
 int resolve_hosts = 0;
 int resolve_services = 1;
@@ -50,6 +53,11 @@ int show_users = 0;
 int show_mem = 0;
 int show_tcpinfo = 0;
 int show_bpf = 0;
+#if HAVE_SELINUX
+int show_context = 0;
+/* If show_users & show_context only do user_ent_hash_build() once */
+int user_ent_hash_build_init = 0;
+#endif
 
 int netid_width;
 int state_width;
@@ -207,7 +215,11 @@ struct user_ent {
 	unsigned int	ino;
 	int		pid;
 	int		fd;
-	char		process[0];
+	char	*process;
+#if HAVE_SELINUX
+	security_context_t	process_ctx;
+	security_context_t	socket_ctx;
+#endif
 };
 
 #define USER_ENT_HASH_SIZE	256
@@ -220,20 +232,29 @@ static int user_ent_hashfn(unsigned int ino)
 	return val & (USER_ENT_HASH_SIZE - 1);
 }
 
-static void user_ent_add(unsigned int ino, const char *process, int pid, int fd)
+#if HAVE_SELINUX
+static void user_ent_add(unsigned int ino, char *process,
+							int pid, int fd,
+							security_context_t proc_ctx,
+							security_context_t sock_ctx)
+#else
+static void user_ent_add(unsigned int ino, char *process, int pid, int fd)
+#endif
 {
 	struct user_ent *p, **pp;
-	int str_len;
 
-	str_len = strlen(process) + 1;
-	p = malloc(sizeof(struct user_ent) + str_len);
+	p = malloc(sizeof(struct user_ent));
 	if (!p)
 		abort();
 	p->next = NULL;
 	p->ino = ino;
 	p->pid = pid;
 	p->fd = fd;
-	strcpy(p->process, process);
+	p->process = strdup(process);
+#if HAVE_SELINUX
+	p->process_ctx = strdup(proc_ctx);
+	p->socket_ctx = strdup(sock_ctx);
+#endif
 
 	pp = &user_ent_hash[user_ent_hashfn(ino)];
 	p->next = *pp;
@@ -247,6 +268,17 @@ static void user_ent_hash_build(void)
 	char name[1024];
 	int nameoff;
 	DIR *dir;
+#if HAVE_SELINUX
+    security_context_t pid_context;
+    security_context_t sock_context;
+	security_context_t no_ctx = "not available";
+
+	/* If show_users & show_context only do this once */
+	if (user_ent_hash_build_init != 0)
+		return;
+
+	user_ent_hash_build_init = 1;
+#endif
 
 	strcpy(name, root);
 	if (strlen(name) == 0 || name[strlen(name)-1] != '/')
@@ -261,19 +293,24 @@ static void user_ent_hash_build(void)
 	while ((d = readdir(dir)) != NULL) {
 		struct dirent *d1;
 		char process[16];
+		char *p;
 		int pid, pos;
 		DIR *dir1;
 		char crap;
 
 		if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
 			continue;
-
+#if HAVE_SELINUX
+		if (getpidcon(pid, &pid_context) != 0)
+			pid_context = strdup(no_ctx);
+#endif
 		sprintf(name + nameoff, "%d/fd/", pid);
 		pos = strlen(name);
 		if ((dir1 = opendir(name)) == NULL)
 			continue;
 
 		process[0] = '\0';
+		p = process;
 
 		while ((d1 = readdir(dir1)) != NULL) {
 			const char *pattern = "socket:[";
@@ -281,6 +318,7 @@ static void user_ent_hash_build(void)
 			char lnk[64];
 			int fd;
 			ssize_t link_len;
+			char tmp[1024];
 
 			if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
 				continue;
@@ -296,21 +334,33 @@ static void user_ent_hash_build(void)
 				continue;
 
 			sscanf(lnk, "socket:[%u]", &ino);
-
-			if (process[0] == '\0') {
-				char tmp[1024];
+#if HAVE_SELINUX
+			snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s",
+					root, pid, d1->d_name);
+
+			if (getfilecon(tmp, &sock_context) < 0)
+				sock_context = strdup(no_ctx);
+#endif
+			if (*p == '\0') {
 				FILE *fp;
 
 				snprintf(tmp, sizeof(tmp), "%s/%d/stat", root, pid);
 				if ((fp = fopen(tmp, "r")) != NULL) {
-					fscanf(fp, "%*d (%[^)])", process);
+					fscanf(fp, "%*d (%[^)])", p);
 					fclose(fp);
 				}
 			}
-
-			user_ent_add(ino, process, pid, fd);
+#if HAVE_SELINUX
+			user_ent_add(ino, p, pid, fd, pid_context, sock_context);
+			freecon(sock_context);
+		}
+		freecon(pid_context);
+		closedir(dir1);
+#else
+			user_ent_add(ino, p, pid, fd);
 		}
 		closedir(dir1);
+#endif
 	}
 	closedir(dir);
 }
@@ -349,6 +399,43 @@ static int find_users(unsigned ino, char *buf, int buflen)
 	return cnt;
 }
 
+#if HAVE_SELINUX
+static int find_context(unsigned ino, char *buf, int buflen)
+{
+	struct user_ent *p;
+	int cnt = 0;
+	char *ptr;
+
+	if (!ino)
+		return 0;
+
+	p = user_ent_hash[user_ent_hashfn(ino)];
+	ptr = buf;
+	while (p) {
+		if (p->ino != ino)
+			goto next;
+
+		if (ptr - buf >= buflen - 1)
+			break;
+
+		snprintf(ptr, buflen - (ptr - buf),
+				"proc_ctx=%s sock_ctx=%s ",
+				p->process_ctx, p->socket_ctx);
+
+		ptr += strlen(ptr);
+		cnt++;
+
+	next:
+		p = p->next;
+	}
+
+	if (ptr != buf)
+		ptr[-1] = '\0';
+
+	return cnt;
+}
+#endif
+
 /* Get stats from slab */
 
 struct slabstat
@@ -1282,11 +1369,17 @@ static int tcp_show_line(char *line, const struct filter *f, int family)
 		if (s.qack&1)
 			printf(" bidir");
 	}
+	char ubuf[4096];
 	if (show_users) {
-		char ubuf[4096];
 		if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0)
 			printf(" users:(%s)", ubuf);
 	}
+#if HAVE_SELINUX
+	if (show_context) {
+		if (find_context(s.ino, ubuf, sizeof(ubuf)) > 0)
+			printf(" %s", ubuf);
+	}
+#endif
 	if (show_details) {
 		if (s.uid)
 			printf(" uid:%u", (unsigned)s.uid);
@@ -1506,11 +1599,17 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f)
 			       r->idiag_retrans);
 		}
 	}
+	char ubuf[4096];
 	if (show_users) {
-		char ubuf[4096];
 		if (find_users(r->idiag_inode, ubuf, sizeof(ubuf)) > 0)
 			printf(" users:(%s)", ubuf);
 	}
+#if HAVE_SELINUX
+	if (show_context) {
+		if (find_context(r->idiag_inode, ubuf, sizeof(ubuf)) > 0)
+			printf(" %s", ubuf);
+	}
+#endif
 	if (show_details) {
 		if (r->idiag_uid)
 			printf(" uid:%u", (unsigned)r->idiag_uid);
@@ -1995,11 +2094,17 @@ static int dgram_show_line(char *line, const struct filter *f, int family)
 	formatted_print(&s.local, s.lport);
 	formatted_print(&s.remote, s.rport);
 
+	char ubuf[4096];
 	if (show_users) {
-		char ubuf[4096];
 		if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0)
 			printf(" users:(%s)", ubuf);
 	}
+#if HAVE_SELINUX
+	if (show_context) {
+		if (find_context(s.ino, ubuf, sizeof(ubuf)) > 0)
+			printf(" %s", ubuf);
+	}
+#endif
 
 	if (show_details) {
 		if (s.uid)
@@ -2185,11 +2290,17 @@ static void unix_list_print(struct unixstat *list, struct filter *f)
 		printf("%*s %-*d %*s %-*d",
 		       addr_width, s->name ? : "*", serv_width, s->ino,
 		       addr_width, peer, serv_width, s->peer);
+		char ubuf[4096];
 		if (show_users) {
-			char ubuf[4096];
 			if (find_users(s->ino, ubuf, sizeof(ubuf)) > 0)
 				printf(" users:(%s)", ubuf);
 		}
+#if HAVE_SELINUX
+		if (show_context) {
+			if (find_context(s->ino, ubuf, sizeof(ubuf)) > 0)
+				printf(" %s", ubuf);
+		}
+#endif
 		printf("\n");
 	}
 }
@@ -2250,11 +2361,17 @@ static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
 			addr_width, "*", /* FIXME */
 			serv_width, peer_ino);
 
+	char ubuf[4096];
 	if (show_users) {
-		char ubuf[4096];
 		if (find_users(r->udiag_ino, ubuf, sizeof(ubuf)) > 0)
 			printf(" users:(%s)", ubuf);
 	}
+#if HAVE_SELINUX
+	if (show_context) {
+		if (find_context(r->udiag_ino, ubuf, sizeof(ubuf)) > 0)
+			printf(" %s", ubuf);
+	}
+#endif
 
 	if (show_mem) {
 		printf("\n\t");
@@ -2511,11 +2628,17 @@ static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f)
 	printf("%*s*%-*s",
 	       addr_width, "", serv_width, "");
 
+	char ubuf[4096];
 	if (show_users) {
-		char ubuf[4096];
 		if (find_users(r->pdiag_ino, ubuf, sizeof(ubuf)) > 0)
 			printf(" users:(%s)", ubuf);
 	}
+#if HAVE_SELINUX
+	if (show_context) {
+		if (find_context(r->pdiag_ino, ubuf, sizeof(ubuf)) > 0)
+			printf(" %s", ubuf);
+	}
+#endif
 	if (show_details) {
 		__u32 uid = 0;
 
@@ -2706,11 +2829,17 @@ static int packet_show(struct filter *f)
 		printf("%*s*%-*s",
 		       addr_width, "", serv_width, "");
 
+		char ubuf[4096];
 		if (show_users) {
-			char ubuf[4096];
 			if (find_users(ino, ubuf, sizeof(ubuf)) > 0)
 				printf(" users:(%s)", ubuf);
 		}
+#if HAVE_SELINUX
+		if (show_context) {
+			if (find_context(ino, ubuf, sizeof(ubuf)) > 0)
+				printf(" %s", ubuf);
+		}
+#endif
 		if (show_details) {
 			printf(" ino=%u uid=%u sk=%llx", ino, uid, sk);
 		}
@@ -2785,6 +2914,29 @@ static void netlink_show_one(struct filter *f,
 		printf("%*s*%-*s",
 		       addr_width, "", serv_width, "");
 	}
+#if HAVE_SELINUX
+    security_context_t pid_context = NULL;
+
+	if (show_context) {
+		/* The pid value will either be:
+		 *		0 if destination is kernel - show kernel initial context.
+		 *		A valid process pid - use getpidcon.
+		 *		A unique value allocated by the kernel or netlink user
+		 *		to the process - show context as "not available".
+		 */
+		if (!pid) {
+			security_get_initial_context("kernel", &pid_context);
+		} else if (pid > 0) {
+			getpidcon(pid, &pid_context);
+		}
+		if (pid_context != NULL) {
+			printf("proc_ctx=%-*s ", serv_width, pid_context);
+			freecon (pid_context);
+		} else {
+			printf("proc_ctx=%-*s ", serv_width, "not available");
+		}
+	}
+# endif
 
 	if (show_details) {
 		printf(" sk=%llx cb=%llx groups=0x%08x", sk, cb, groups);
@@ -3060,6 +3212,7 @@ static void _usage(FILE *dest)
 "   -i, --info		show internal TCP information\n"
 "   -s, --summary	show socket usage summary\n"
 "   -b, --bpf           show bpf filter socket information\n"
+"   -Z, --context	display SELinux security contexts for process and socket\n"
 "\n"
 "   -4, --ipv4          display only IP version 4 sockets\n"
 "   -6, --ipv6          display only IP version 6 sockets\n"
@@ -3149,6 +3302,7 @@ static const struct option long_opts[] = {
 	{ "filter", 1, 0, 'F' },
 	{ "version", 0, 0, 'V' },
 	{ "help", 0, 0, 'h' },
+	{ "context", 0, 0, 'Z' },
 	{ 0 }
 
 };
@@ -3167,7 +3321,7 @@ int main(int argc, char *argv[])
 
 	current_filter.states = default_filter.states;
 
-	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vV",
+	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vV:Z",
 				 long_opts, NULL)) != EOF) {
 		switch(ch) {
 		case 'n':
@@ -3327,6 +3481,19 @@ int main(int argc, char *argv[])
 		case 'V':
 			printf("ss utility, iproute2-ss%s\n", SNAPSHOT);
 			exit(0);
+		case 'Z':
+#if HAVE_SELINUX
+	    	if (is_selinux_enabled() <= 0) {
+				fprintf(stderr, "ss: SELinux is not enabled.\n");
+				exit(1);
+	    	}
+	    	show_context++;
+			user_ent_hash_build();
+#else
+            fprintf(stderr, "ss: version does not support SELinux.\n");
+	    	exit(1);
+#endif
+			break;
 		case 'h':
 		case '?':
 			help();
-- 
1.8.5.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-07 16:22 RFC - Display context information using iproute2 ss utility Richard Haines
@ 2014-02-07 17:03 ` Ole Kliemann
  2014-02-07 21:50   ` Paul Moore
  0 siblings, 1 reply; 7+ messages in thread
From: Ole Kliemann @ 2014-02-07 17:03 UTC (permalink / raw)
  To: Richard Haines; +Cc: selinux list

[-- Attachment #1: Type: text/plain, Size: 7565 bytes --]

On Fri, Feb 07, 2014 at 04:22:37PM +0000, Richard Haines wrote:
> I've been patching the iproute2 "ss" utility to display the SELinux
> security contexts for process and sockets, however I'm not sure
> whether the socket contexts are correct (I expected most to show
> system_u:object_r:....). 
> 
> I'm taking the socket contexts from /proc/PID/fd as was mentioned in
> a previous email regarding socket contexts - is this correct ??

I was doing it that way and it seemed to work, I could even 
change the context using 'chcon /proc/PID/fd'.

But I have no idea whether it is supposed to be a reliable way or 
any other methods exist. The whole sockfs thing kept me rather 
wondering...

> 
> I've attached the patch that is built against:
> 
> git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
> 
> Also is it possible to obtain a sockets peer context from userspace
> using the /proc/PID/fd information as it would be useful to show this.
> 
> Richard

> From 7d61b9f9e5098a594305364e1380c492eef52091 Mon Sep 17 00:00:00 2001
> From: Richard Haines <richard_c_haines@btinternet.com>
> Date: Fri, 7 Feb 2014 15:02:53 +0000
> Subject: [PATCH] ss: Add support for retrieving SELinux contexts
> 
> The SELinux contexts can be added to the output using the -Z option.
> The process and socket contexts are retrieved but for netlink sockets:
> if valid process show process context, if pid = 0 show kernel initial
> context, if unknown show "not available".
> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>  configure     |  16 +++++
>  man/man8/ss.8 |  19 ++++++
>  misc/Makefile |  12 ++++
>  misc/ss.c     | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
>  4 files changed, 235 insertions(+), 21 deletions(-)
> 
> diff --git a/configure b/configure
> index da01c19..854837e 100755
> --- a/configure
> +++ b/configure
> @@ -231,6 +231,19 @@ EOF
>      rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest
>  }
>  
> +check_selinux()
> +# SELinux is a compile time option in the ss utility
> +{
> +	SELINUX_LIB=$(${PKG_CONFIG} --silence-errors libselinux --libs)
> +	if [ -n "$SELINUX_LIB" ]
> +	then
> +	echo "HAVE_SELINUX:=y" >>Config
> +	echo "yes"
> +    else
> +	echo "no"
> +	fi
> +}
> +
>  echo "# Generated config based on" $INCLUDE >Config
>  check_toolchain
>  
> @@ -253,3 +266,6 @@ check_ipt_lib_dir
>  
>  echo -n "libc has setns: "
>  check_setns
> +
> +echo -n "SELinux support: "
> +check_selinux
> diff --git a/man/man8/ss.8 b/man/man8/ss.8
> index 807d9dc..2fbed36 100644
> --- a/man/man8/ss.8
> +++ b/man/man8/ss.8
> @@ -53,6 +53,22 @@ Print summary statistics. This option does not parse socket lists obtaining
>  summary from various sources. It is useful when amount of sockets is so huge
>  that parsing /proc/net/tcp is painful.
>  .TP
> +.B \-Z, \-\-context
> +Show SELinux security contexts. Both the process and socket contexts will
> +be displayed (for those with socket file descriptors). For 
> +.BR netlink (7)
> +sockets, the context displayed is as follows:
> +.RS
> +.RS
> +.IP "1." 4
> +If a valid process show pid context.
> +.IP "2." 4
> +If destination is kernel (pid = 0) show kernel initial context.
> +.IP "3." 4
> +If allocated by the kernel or netlink user show context as "not available".
> +.RE
> +.RE
> +.TP
>  .B \-b, \-\-bpf
>  Show socket BPF filters (only administrators are allowed to get these information).
>  .TP
> @@ -103,6 +119,9 @@ Please take a look at the official documentation (Debian package iproute-doc) fo
>  .B ss -t -a
>  Display all TCP sockets.
>  .TP
> +.B ss -t -a -Z
> +Display all TCP sockets with process and socket SELinux security contexts.
> +.TP
>  .B ss -u -a
>  Display all UDP sockets.
>  .TP
> diff --git a/misc/Makefile b/misc/Makefile
> index a59ff87..a946a85 100644
> --- a/misc/Makefile
> +++ b/misc/Makefile
> @@ -8,6 +8,18 @@ include ../Config
>  all: $(TARGETS)
>  
>  ss: $(SSOBJ)
> +ifeq ($(HAVE_SELINUX),y)
> +	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SSOBJ) $(LDLIBS) -lselinux
> +else
> +	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SSOBJ) $(LDLIBS)
> +endif
> +
> +ss.o: ss.c
> +ifeq ($(HAVE_SELINUX),y)
> +	$(CC) $(CFLAGS) -DHAVE_SELINUX -c $+
> +else
> +	$(CC) $(CFLAGS) -c $+
> +endif
>  
>  nstat: nstat.c
>  	$(CC) $(CFLAGS) $(LDFLAGS) -o nstat nstat.c -lm
> diff --git a/misc/ss.c b/misc/ss.c
> index 764ffe2..1e1d3fb 100644
> --- a/misc/ss.c
> +++ b/misc/ss.c
> @@ -40,6 +40,9 @@
>  #include <linux/filter.h>
>  #include <linux/packet_diag.h>
>  #include <linux/netlink_diag.h>
> +#if HAVE_SELINUX
> +#include <selinux/selinux.h>
> +#endif
>  
>  int resolve_hosts = 0;
>  int resolve_services = 1;
> @@ -50,6 +53,11 @@ int show_users = 0;
>  int show_mem = 0;
>  int show_tcpinfo = 0;
>  int show_bpf = 0;
> +#if HAVE_SELINUX
> +int show_context = 0;
> +/* If show_users & show_context only do user_ent_hash_build() once */
> +int user_ent_hash_build_init = 0;
> +#endif
>  
>  int netid_width;
>  int state_width;
> @@ -207,7 +215,11 @@ struct user_ent {
>  	unsigned int	ino;
>  	int		pid;
>  	int		fd;
> -	char		process[0];
> +	char	*process;
> +#if HAVE_SELINUX
> +	security_context_t	process_ctx;
> +	security_context_t	socket_ctx;
> +#endif
>  };
>  
>  #define USER_ENT_HASH_SIZE	256
> @@ -220,20 +232,29 @@ static int user_ent_hashfn(unsigned int ino)
>  	return val & (USER_ENT_HASH_SIZE - 1);
>  }
>  
> -static void user_ent_add(unsigned int ino, const char *process, int pid, int fd)
> +#if HAVE_SELINUX
> +static void user_ent_add(unsigned int ino, char *process,
> +							int pid, int fd,
> +							security_context_t proc_ctx,
> +							security_context_t sock_ctx)
> +#else
> +static void user_ent_add(unsigned int ino, char *process, int pid, int fd)
> +#endif
>  {
>  	struct user_ent *p, **pp;
> -	int str_len;
>  
> -	str_len = strlen(process) + 1;
> -	p = malloc(sizeof(struct user_ent) + str_len);
> +	p = malloc(sizeof(struct user_ent));
>  	if (!p)
>  		abort();
>  	p->next = NULL;
>  	p->ino = ino;
>  	p->pid = pid;
>  	p->fd = fd;
> -	strcpy(p->process, process);
> +	p->process = strdup(process);
> +#if HAVE_SELINUX
> +	p->process_ctx = strdup(proc_ctx);
> +	p->socket_ctx = strdup(sock_ctx);
> +#endif
>  
>  	pp = &user_ent_hash[user_ent_hashfn(ino)];
>  	p->next = *pp;
> @@ -247,6 +268,17 @@ static void user_ent_hash_build(void)
>  	char name[1024];
>  	int nameoff;
>  	DIR *dir;
> +#if HAVE_SELINUX
> +    security_context_t pid_context;
> +    security_context_t sock_context;
> +	security_context_t no_ctx = "not available";
> +
> +	/* If show_users & show_context only do this once */
> +	if (user_ent_hash_build_init != 0)
> +		return;
> +
> +	user_ent_hash_build_init = 1;
> +#endif
>  
>  	strcpy(name, root);
>  	if (strlen(name) == 0 || name[strlen(name)-1] != '/')
> @@ -261,19 +293,24 @@ static void user_ent_hash_build(void)
>  	while ((d = readdir(dir)) != NULL) {
>  		struct dirent *d1;
>  		char process[16];
> +		char *p;
>  		int pid, pos;
>  		DIR *dir1;
>  		char crap;
>  
>  		if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
>  			continue;
> -
> +#if HAVE_SELINUX
> +		if (getpidcon(pid, &pid_context) != 0)
> +			pid_context = strdup(no_ctx);
> +#endif
>  		sprintf(name + nameoff, "%d/fd/", pid);
>  		pos = strlen(name);
>  		if ((dir1 = opendir(name)) == NULL)
>  			continue;
>  
>  		process[0] = '

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-07 17:03 ` Ole Kliemann
@ 2014-02-07 21:50   ` Paul Moore
  2014-02-09 16:27     ` Richard Haines
  2014-02-17 20:10     ` Ole Kliemann
  0 siblings, 2 replies; 7+ messages in thread
From: Paul Moore @ 2014-02-07 21:50 UTC (permalink / raw)
  To: Ole Kliemann, Richard Haines; +Cc: selinux

On Friday, February 07, 2014 06:03:25 PM Ole Kliemann wrote:
> On Fri, Feb 07, 2014 at 04:22:37PM +0000, Richard Haines wrote:
> > I've been patching the iproute2 "ss" utility to display the SELinux
> > security contexts for process and sockets, however I'm not sure
> > whether the socket contexts are correct (I expected most to show
> > system_u:object_r:....).
> > 
> > I'm taking the socket contexts from /proc/PID/fd as was mentioned in
> > a previous email regarding socket contexts - is this correct ??
> 
> I was doing it that way and it seemed to work ...

What you will see is the label of the socket's associated inode, not the 
actual socket label.

> ... I could even change the context using 'chcon /proc/PID/fd'.

Yes, you really shouldn't do that.  I've actually got a patch kicking around 
that I haven't had the time to test which will actually prevent you from 
changing a socket's inode label. 

> But I have no idea whether it is supposed to be a reliable way or
> any other methods exist. The whole sockfs thing kept me rather
> wondering...

It works as far as I know, it just turns out that it isn't quite what you 
think it is :)

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-07 21:50   ` Paul Moore
@ 2014-02-09 16:27     ` Richard Haines
  2014-02-11 23:17       ` Paul Moore
  2014-02-17 20:10     ` Ole Kliemann
  1 sibling, 1 reply; 7+ messages in thread
From: Richard Haines @ 2014-02-09 16:27 UTC (permalink / raw)
  To: Paul Moore; +Cc: selinux

Thanks for clarifying the socket fd context.

For the iproute ss utility I was thinking of altering the man page to
reflect your comments (added below) and some testing I've done using
policy role/type and range transition statements.

Overall do you think it is worth adding the socket contexts to the ss utility.


-Z, --context
    Show SELinux security contexts. The context of the process using
    the socket and the sockets context will be displayed. The socket
    context is taken from the file descriptors inode and is not the
    actual socket context held by the kernel. Sockets are typically
    labeled with the context of the creating process, however the
    context shown will reflect any policy role, type and/or range
    transition rules applied, and is therefore a useful reference.

    For netlink(7) sockets the initiating process context is displayed
    as follows:

      1. If valid pid show the process context.

      2. If destination is kernel (pid = 0) show kernel initial context.

      3. If a unique identifier has been allocated by the kernel or
         netlink user, show context as "not available".
         This will generally indicate that a process has more
         than one netlink socket active.

Richard



----- Original Message -----
> From: Paul Moore <paul@paul-moore.com>
> To: Ole Kliemann <ole@plastictree.net>; Richard Haines <richard_c_haines@btinternet.com>
> Cc: selinux@tycho.nsa.gov
> Sent: Friday, 7 February 2014, 21:50
> Subject: Re: RFC - Display context information using iproute2 ss utility
> 
> On Friday, February 07, 2014 06:03:25 PM Ole Kliemann wrote:
>>  On Fri, Feb 07, 2014 at 04:22:37PM +0000, Richard Haines wrote:
>>  > I've been patching the iproute2 "ss" utility to display 
> the SELinux
>>  > security contexts for process and sockets, however I'm not sure
>>  > whether the socket contexts are correct (I expected most to show
>>  > system_u:object_r:....).
>>  > 
>>  > I'm taking the socket contexts from /proc/PID/fd as was mentioned 
> in
>>  > a previous email regarding socket contexts - is this correct ??
>> 
>>  I was doing it that way and it seemed to work ...
> 
> What you will see is the label of the socket's associated inode, not the 
> actual socket label.
> 
>>  ... I could even change the context using 'chcon /proc/PID/fd'.
> 
> Yes, you really shouldn't do that.  I've actually got a patch kicking 
> around 
> that I haven't had the time to test which will actually prevent you from 
> changing a socket's inode label. 
> 
>>  But I have no idea whether it is supposed to be a reliable way or
>>  any other methods exist. The whole sockfs thing kept me rather
>>  wondering...
> 
> It works as far as I know, it just turns out that it isn't quite what you 
> think it is :)
> 
> -- 
> paul moore
> www.paul-moore.com
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-09 16:27     ` Richard Haines
@ 2014-02-11 23:17       ` Paul Moore
  0 siblings, 0 replies; 7+ messages in thread
From: Paul Moore @ 2014-02-11 23:17 UTC (permalink / raw)
  To: Richard Haines; +Cc: selinux

On Sunday, February 09, 2014 04:27:46 PM Richard Haines wrote:
> Thanks for clarifying the socket fd context.
> 
> For the iproute ss utility I was thinking of altering the man page to
> reflect your comments (added below) and some testing I've done using
> policy role/type and range transition statements.
> 
> Overall do you think it is worth adding the socket contexts to the ss
> utility.

I'm pretty conflicted on this ... at best I wonder how useful the information 
will be to users/developers and at worst I fear it could end up being 
misleading.

> -Z, --context
>     Show SELinux security contexts. The context of the process using
>     the socket and the sockets context will be displayed. The socket
>     context is taken from the file descriptors inode and is not the

I might say that the socket context is taken from the "associated inode" and 
leave the file descriptor out of it, but that is just me.  After all, there is 
a reason I'm not a writer :)

>     actual socket context held by the kernel. Sockets are typically
>     labeled with the context of the creating process, however the
>     context shown will reflect any policy role, type and/or range
>     transition rules applied, and is therefore a useful reference.
>
>     For netlink(7) sockets the initiating process context is displayed
>     as follows:
> 
>       1. If valid pid show the process context.
> 
>       2. If destination is kernel (pid = 0) show kernel initial context.
> 
>       3. If a unique identifier has been allocated by the kernel or
>          netlink user, show context as "not available".
>          This will generally indicate that a process has more
>          than one netlink socket active.
> 
> Richard

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-07 21:50   ` Paul Moore
  2014-02-09 16:27     ` Richard Haines
@ 2014-02-17 20:10     ` Ole Kliemann
  2014-02-17 21:38       ` Paul Moore
  1 sibling, 1 reply; 7+ messages in thread
From: Ole Kliemann @ 2014-02-17 20:10 UTC (permalink / raw)
  To: Paul Moore; +Cc: selinux

[-- Attachment #1: Type: text/plain, Size: 1688 bytes --]

On Fri, Feb 07, 2014 at 04:50:22PM -0500, Paul Moore wrote:
> On Friday, February 07, 2014 06:03:25 PM Ole Kliemann wrote:
> > On Fri, Feb 07, 2014 at 04:22:37PM +0000, Richard Haines wrote:
> > > I've been patching the iproute2 "ss" utility to display the SELinux
> > > security contexts for process and sockets, however I'm not sure
> > > whether the socket contexts are correct (I expected most to show
> > > system_u:object_r:....).
> > > 
> > > I'm taking the socket contexts from /proc/PID/fd as was mentioned in
> > > a previous email regarding socket contexts - is this correct ??
> > 
> > I was doing it that way and it seemed to work ...
> 
> What you will see is the label of the socket's associated inode, not the 
> actual socket label.
> 
> > ... I could even change the context using 'chcon /proc/PID/fd'.
> 
> Yes, you really shouldn't do that.  I've actually got a patch kicking around 
> that I haven't had the time to test which will actually prevent you from 
> changing a socket's inode label. 
> 
> > But I have no idea whether it is supposed to be a reliable way or
> > any other methods exist. The whole sockfs thing kept me rather
> > wondering...
> 
> It works as far as I know, it just turns out that it isn't quite what you 
> think it is :)

Thanks for clarification. 

On a related question: Is it the same with pipes? I just 
realized, in one of my programs I am actually using setfilecon on 
/proc/self/fd/some_pipe to change the context of a pipe.

Do I have to expect this to break in a later kernel patch?

If yes, what would be the correct way? Do I have to use explicit 
FIFO files to be able to do this?

Ole

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC - Display context information using iproute2 ss utility
  2014-02-17 20:10     ` Ole Kliemann
@ 2014-02-17 21:38       ` Paul Moore
  0 siblings, 0 replies; 7+ messages in thread
From: Paul Moore @ 2014-02-17 21:38 UTC (permalink / raw)
  To: Ole Kliemann; +Cc: selinux

On Monday, February 17, 2014 09:10:21 PM Ole Kliemann wrote:
> On Fri, Feb 07, 2014 at 04:50:22PM -0500, Paul Moore wrote:
> > On Friday, February 07, 2014 06:03:25 PM Ole Kliemann wrote:
> > > On Fri, Feb 07, 2014 at 04:22:37PM +0000, Richard Haines wrote:
> > > > I've been patching the iproute2 "ss" utility to display the SELinux
> > > > security contexts for process and sockets, however I'm not sure
> > > > whether the socket contexts are correct (I expected most to show
> > > > system_u:object_r:....).
> > > > 
> > > > I'm taking the socket contexts from /proc/PID/fd as was mentioned in
> > > > a previous email regarding socket contexts - is this correct ??
> > > 
> > > I was doing it that way and it seemed to work ...
> > 
> > What you will see is the label of the socket's associated inode, not the
> > actual socket label.
> > 
> > > ... I could even change the context using 'chcon /proc/PID/fd'.
> > 
> > Yes, you really shouldn't do that.  I've actually got a patch kicking
> > around that I haven't had the time to test which will actually prevent
> > you from changing a socket's inode label.
> > 
> > > But I have no idea whether it is supposed to be a reliable way or
> > > any other methods exist. The whole sockfs thing kept me rather
> > > wondering...
> > 
> > It works as far as I know, it just turns out that it isn't quite what you
> > think it is :)
> 
> Thanks for clarification.
> 
> On a related question: Is it the same with pipes? I just
> realized, in one of my programs I am actually using setfilecon on
> /proc/self/fd/some_pipe to change the context of a pipe.
> 
> Do I have to expect this to break in a later kernel patch?
> 
> If yes, what would be the correct way? Do I have to use explicit
> FIFO files to be able to do this?

As you've probably figured out by now, sockets are just a little bit odd from 
a SELinux point of view.  The good news, in relation to your question, is that 
pipes are entirely different from sockets from a SELinux perspective.  Pipes 
should behave like normal fds with no hidden labels/properties.

-Paul

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-02-17 21:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-07 16:22 RFC - Display context information using iproute2 ss utility Richard Haines
2014-02-07 17:03 ` Ole Kliemann
2014-02-07 21:50   ` Paul Moore
2014-02-09 16:27     ` Richard Haines
2014-02-11 23:17       ` Paul Moore
2014-02-17 20:10     ` Ole Kliemann
2014-02-17 21:38       ` Paul Moore

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.