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.