From 1bc2695744c729804af32d48ce68854cba4de8f7 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 10 May 2011 02:42:17 +0200 Subject: Allows run with restricted privileges. Adds option -u and -g to specify user and group. When different user (than root) is specified, linux capabilities CAP_NET_* are kept. --- sysdep/linux/Modules | 1 + sysdep/linux/syspriv.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 sysdep/linux/syspriv.h (limited to 'sysdep/linux') diff --git a/sysdep/linux/Modules b/sysdep/linux/Modules index 1b867d8..09f4a47 100644 --- a/sysdep/linux/Modules +++ b/sysdep/linux/Modules @@ -3,3 +3,4 @@ krt-scan.c krt-scan.h #endif sysio.h +syspriv.h diff --git a/sysdep/linux/syspriv.h b/sysdep/linux/syspriv.h new file mode 100644 index 0000000..bfe19ac --- /dev/null +++ b/sysdep/linux/syspriv.h @@ -0,0 +1,62 @@ + +#include +#include + +#ifndef _LINUX_CAPABILITY_VERSION_3 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#define _LINUX_CAPABILITY_U32S_3 2 +#endif + +/* capset() prototype is missing ... */ +int capset(cap_user_header_t hdrp, const cap_user_data_t datap); + +static inline int +set_capabilities(u32 caps) +{ + struct __user_cap_header_struct cap_hdr; + struct __user_cap_data_struct cap_dat[_LINUX_CAPABILITY_U32S_3]; + int err; + + cap_hdr.version = _LINUX_CAPABILITY_VERSION_3; + cap_hdr.pid = 0; + + memset(cap_dat, 0, sizeof(cap_dat)); + cap_dat[0].effective = cap_dat[0].permitted = caps; + + err = capset(&cap_hdr, cap_dat); + if (!err) + return 0; + + /* Kernel may support do not support our version of capability interface. + The last call returned supported version so we just retry it. */ + if (errno == EINVAL) + { + err = capset(&cap_hdr, cap_dat); + if (!err) + return 0; + } + + return -1; +} + +static void +drop_uid(uid_t uid) +{ + u32 caps = + CAP_TO_MASK(CAP_NET_BIND_SERVICE) | + CAP_TO_MASK(CAP_NET_BROADCAST) | + CAP_TO_MASK(CAP_NET_ADMIN) | + CAP_TO_MASK(CAP_NET_RAW); + + if (seteuid(uid) < 0) + die("seteuid: %m"); + + if (set_capabilities(caps) < 0) + die("capset: %m"); + + if (prctl(PR_SET_KEEPCAPS, 1) < 0) + die("prctl: %m"); + + if (setresuid(uid, uid, uid) < 0) + die("setresuid: %m"); +} -- cgit v1.2.3