Re: RFC - Display context information using iproute2 ss utility

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx>
> 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@xxxxxxxxxxxxxx>
> ---
>  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] = '
_______________________________________________
Selinux mailing list
Selinux@xxxxxxxxxxxxx
To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx.
To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux