* [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed
@ 2015-02-23 19:18 Sven Eckelmann
2015-02-28 20:04 ` MK
2015-03-11 12:07 ` Simon Wunderlich
0 siblings, 2 replies; 5+ messages in thread
From: Sven Eckelmann @ 2015-02-23 19:18 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
The alfred process only requires the capability to bind to a raw socket
(CAP_NET_RAW). It is enough to mark this capability as permitted on program
startup and mark it again as effective whenever a new netsock is initialized.
All other capabilities can be dropped completely.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
Makefile | 24 ++++++++++++++++++
main.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
netsock.c | 44 +++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 8e944c9..4e22d76 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,9 @@ MANPAGE = man/alfred.8
CFLAGS += -pedantic -Wall -W -std=gnu99 -fno-strict-aliasing -MD -MP
LDLIBS += -lrt
+# B.A.T.M.A.N. debugging:
+export CONFIG_ALFRED_CAPABILITIES=y
+
# disable verbose output
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
@@ -70,6 +73,27 @@ ifneq ($(CONFIG_ALFRED_GPSD),n)
GPSD_INSTALL=gpsd-install
endif
+ifneq ($(CONFIG_ALFRED_CAPABILITIES),n)
+ ifeq ($(origin PKG_CONFIG), undefined)
+ PKG_CONFIG = pkg-config
+ ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
+ $(error $(PKG_CONFIG) not found)
+ endif
+ endif
+
+ ifeq ($(origin LIBCAP_CFLAGS) $(origin LIBCAP_LDLIBS), undefined undefined)
+ LIBCAP_NAME ?= libcap
+ ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBCAP_NAME) 2>/dev/null),)
+ $(error No $(LIBCAP_NAME) development libraries found!)
+ endif
+ LIBCAP_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBCAP_NAME))
+ LIBCAP_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBCAP_NAME))
+ endif
+ CFLAGS += $(LIBCAP_CFLAGS)
+ CPPFLAGS += -DCONFIG_ALFRED_CAPABILITIES
+ LDLIBS += $(LIBCAP_LDLIBS)
+endif
+
# default target
all: $(BINARY_NAME) $(VIS_ALL) $(GPSD_ALL)
diff --git a/main.c b/main.c
index d298d65..982bd2a 100644
--- a/main.c
+++ b/main.c
@@ -24,6 +24,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef CONFIG_ALFRED_CAPABILITIES
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <unistd.h>
+#endif
#include "alfred.h"
#include "packet.h"
#include "list.h"
@@ -60,9 +65,82 @@ static void alfred_usage(void)
printf("\n");
}
+static int reduce_capabilities(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_ALFRED_CAPABILITIES
+ cap_t cap_cur;
+ cap_t cap_new;
+ cap_flag_value_t cap_flag;
+ cap_value_t cap_net_raw = CAP_NET_RAW;
+
+ /* get current process capabilities */
+ cap_cur = cap_get_proc();
+ if (!cap_cur) {
+ perror("cap_get_proc");
+ return -1;
+ }
+
+ /* create new capabilities */
+ cap_new = cap_init();
+ if (!cap_new) {
+ perror("cap_init");
+ cap_free(cap_new);
+ return -1;
+ }
+
+ /* copy capability as non-effictive but permitted */
+ cap_flag = CAP_CLEAR;
+ cap_get_flag(cap_cur, CAP_NET_RAW, CAP_PERMITTED, &cap_flag);
+ if (cap_flag != CAP_CLEAR) {
+ ret = cap_set_flag(cap_new, CAP_PERMITTED, 1, &cap_net_raw,
+ CAP_SET);
+ if (ret < 0) {
+ perror("cap_set_flag");
+ goto out;
+ }
+ }
+
+ /* set minimal capabilities field */
+ ret = cap_set_proc(cap_new);
+ if (ret < 0) {
+ perror("cap_set_proc");
+ goto out;
+ }
+
+ /* don't drop capabilities with setuid */
+ ret = prctl(PR_SET_KEEPCAPS, 1);
+ if (ret < 0) {
+ perror("prctl PR_SET_KEEPCAPS(1)");
+ goto out;
+ }
+
+ /* drop euid */
+ ret = setuid(getuid());
+ if (ret < 0) {
+ perror("setuid");
+ goto out;
+ }
+
+ /* drop capabilities with setuid */
+ ret = prctl(PR_SET_KEEPCAPS, 0);
+ if (ret < 0) {
+ perror("prctl PR_SET_KEEPCAPS(0)");
+ goto out;
+ }
+
+out:
+ cap_free(cap_new);
+ cap_free(cap_cur);
+#endif
+
+ return ret;
+}
+
static struct globals *alfred_init(int argc, char *argv[])
{
- int opt, opt_ind, i;
+ int opt, opt_ind, i, ret;
struct globals *globals;
struct option long_options[] = {
{"set-data", required_argument, NULL, 's'},
@@ -78,6 +156,10 @@ static struct globals *alfred_init(int argc, char *argv[])
{NULL, 0, NULL, 0},
};
+ ret = reduce_capabilities();
+ if (ret < 0)
+ return NULL;
+
globals = &alfred_globals;
memset(globals, 0, sizeof(*globals));
diff --git a/netsock.c b/netsock.c
index cc2e9a5..592f3e3 100644
--- a/netsock.c
+++ b/netsock.c
@@ -34,6 +34,9 @@
#include <sys/types.h>
#include <stdlib.h>
#include <sys/select.h>
+#ifdef CONFIG_ALFRED_CAPABILITIES
+#include <sys/capability.h>
+#endif
#include "alfred.h"
#include "batadv_query.h"
#include "packet.h"
@@ -165,6 +168,45 @@ int netsock_set_interfaces(struct globals *globals, char *interfaces)
return 0;
}
+static int enable_raw_bind_capability(int enable)
+{
+ int ret = 0;
+
+#ifdef CONFIG_ALFRED_CAPABILITIES
+ cap_t cap_cur;
+ cap_flag_value_t cap_flag;
+ cap_value_t cap_net_raw = CAP_NET_RAW;
+
+ if (enable)
+ cap_flag = CAP_SET;
+ else
+ cap_flag = CAP_CLEAR;
+
+ cap_cur = cap_get_proc();
+ if (!cap_cur) {
+ perror("cap_get_proc");
+ return -1;
+ }
+
+ ret = cap_set_flag(cap_cur, CAP_EFFECTIVE, 1, &cap_net_raw, cap_flag);
+ if (ret < 0) {
+ perror("cap_set_flag");
+ goto out;
+ }
+
+ ret = cap_set_proc(cap_cur);
+ if (ret < 0) {
+ perror("cap_set_proc");
+ goto out;
+ }
+
+out:
+ cap_free(cap_cur);
+#endif
+
+ return ret;
+}
+
static int netsock_open(struct interface *interface)
{
int sock;
@@ -204,11 +246,13 @@ static int netsock_open(struct interface *interface)
memcpy(&interface->hwaddr, &ifr.ifr_hwaddr.sa_data, 6);
mac_to_ipv6(&interface->hwaddr, &interface->address);
+ enable_raw_bind_capability(1);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interface->interface,
strlen(interface->interface) + 1)) {
perror("can't bind to device");
goto err;
}
+ enable_raw_bind_capability(0);
if (bind(sock, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
perror("can't bind");
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed
2015-02-23 19:18 [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed Sven Eckelmann
@ 2015-02-28 20:04 ` MK
2015-02-28 22:36 ` Simon Wunderlich
2015-03-05 8:05 ` Sven Eckelmann
2015-03-11 12:07 ` Simon Wunderlich
1 sibling, 2 replies; 5+ messages in thread
From: MK @ 2015-02-28 20:04 UTC (permalink / raw)
To: b.a.t.m.a.n
Hi!
Thanks for the patch. Setup seems to be still working. How can I verify that
privileges really dropped?
There are further questions:
Is _read_ access for the alfred user (resp. group) sufficient in
/sys/kernel/debug/batman_adv/* ?
Or is write access on the socket file in this directory mandatory for full
functionality?
Thanks
Martin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed
2015-02-28 20:04 ` MK
@ 2015-02-28 22:36 ` Simon Wunderlich
2015-03-05 8:05 ` Sven Eckelmann
1 sibling, 0 replies; 5+ messages in thread
From: Simon Wunderlich @ 2015-02-28 22:36 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: MK
[-- Attachment #1: Type: text/plain, Size: 529 bytes --]
On Saturday 28 February 2015 21:04:19 MK wrote:
> Hi!
>
> Thanks for the patch. Setup seems to be still working. How can I verify that
> privileges really dropped?
>
> There are further questions:
>
> Is _read_ access for the alfred user (resp. group) sufficient in
> /sys/kernel/debug/batman_adv/* ?
> Or is write access on the socket file in this directory mandatory for full
> functionality?
Read functionality should be enough. We are only reading the originator table
and (global) translation table.
Cheers,
Simon
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed
2015-02-28 20:04 ` MK
2015-02-28 22:36 ` Simon Wunderlich
@ 2015-03-05 8:05 ` Sven Eckelmann
1 sibling, 0 replies; 5+ messages in thread
From: Sven Eckelmann @ 2015-03-05 8:05 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: MK
Hi,
Please Cc me when you want an answer from me (I am not subscribed to this
mailing list). I just found this mail by pure luck.
On Saturday 28 February 2015 21:04:19 MK wrote:
> Thanks for the patch. Setup seems to be still working. How can I verify that
> privileges really dropped?
The privileges of a process can be found in
$ cat /proc/`pidof alfred`/status
The active capabilities are CapEff. The capabilities the process can request
can be found in CapPrm.
> There are further questions:
>
> Is _read_ access for the alfred user (resp. group) sufficient in
> /sys/kernel/debug/batman_adv/* ?
> Or is write access on the socket file in this directory mandatory for full
> functionality?
The process needs to access the path and read the files. For example my system
allows read of this files by default BUT disallows non-root access to
/sys/kernel/debug
$ ls -ltrd /sys/kernel/debug
drwx------ 27 root root 0 Mar 2 18:58 /sys/kernel/debug
I would have to allow other users o+rx access to this path before being able
to access the batman-adv files:
$ cat /sys/kernel/debug/batman_adv/bat0/originators
cat: /sys/kernel/debug/batman_adv/bat0/originators: Permission denied
$ sudo chmod o+rx /sys/kernel/debug
$ cat /sys/kernel/debug/batman_adv/bat0/originators
[B.A.T.M.A.N. adv 2014.3.0, MainIF/MAC: eth0/XX:XX:XX:XX:XX:XX (bat0
BATMAN_IV)]
Originator last-seen (#/255) Nexthop [outgoingIF]:
Potential nexthops ...
No batman nodes in range ...
!!!! WARNING !!!!
I don't recommend to grant all users access to /sys/kernel/debug.
Kind regards,
Sven
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed
2015-02-23 19:18 [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed Sven Eckelmann
2015-02-28 20:04 ` MK
@ 2015-03-11 12:07 ` Simon Wunderlich
1 sibling, 0 replies; 5+ messages in thread
From: Simon Wunderlich @ 2015-03-11 12:07 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
[-- Attachment #1: Type: text/plain, Size: 501 bytes --]
On Monday 23 February 2015 20:18:50 Sven Eckelmann wrote:
> The alfred process only requires the capability to bind to a raw socket
> (CAP_NET_RAW). It is enough to mark this capability as permitted on program
> startup and mark it again as effective whenever a new netsock is
> initialized. All other capabilities can be dropped completely.
>
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
Applied in revision b0877b3 (just replaced that "B.A.T.M.A.N. debugging
comment).
Thanks!
Simon
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-03-11 12:07 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-23 19:18 [B.A.T.M.A.N.] [PATCH] alfred: Drop capabilities when not needed Sven Eckelmann
2015-02-28 20:04 ` MK
2015-02-28 22:36 ` Simon Wunderlich
2015-03-05 8:05 ` Sven Eckelmann
2015-03-11 12:07 ` Simon Wunderlich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).