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.
This commit is contained in:
parent
46bb7e0d17
commit
1bc2695744
6 changed files with 150 additions and 2 deletions
|
@ -6,6 +6,7 @@ CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
|
|||
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
|
||||
CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
|
||||
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
|
||||
CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
|
||||
|
||||
CONFIG_UNIX_IFACE Use Unix interface scanner
|
||||
CONFIG_UNIX_SET Use Unix route setting
|
||||
|
@ -19,3 +20,4 @@ CONFIG_UNNUM_MULTICAST krt-iface: We support multicasts on unnumbered PtP device
|
|||
CONFIG_LINUX_MC_MREQN Linux: Use struct mreqn for multicasting
|
||||
CONFIG_LINUX_MC_MREQ Linux: Use struct mreq
|
||||
CONFIG_LINUX_MC_MREQ_BIND Linux: Use struct mreq and SO_BINDTODEVICE
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#define CONFIG_LINUX_MC_MREQN
|
||||
#define CONFIG_UNIX_DONTROUTE
|
||||
|
||||
#define CONFIG_RESTRICTED_PRIVILEGES
|
||||
|
||||
/*
|
||||
Link: sysdep/linux/netlink
|
||||
Link: sysdep/linux
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#define CONFIG_MULTIPLE_TABLES
|
||||
#define CONFIG_ALL_TABLES_AT_ONCE
|
||||
|
||||
#define CONFIG_RESTRICTED_PRIVILEGES
|
||||
|
||||
/*
|
||||
Link: sysdep/linux/netlink
|
||||
Link: sysdep/linux
|
||||
|
|
|
@ -3,3 +3,4 @@ krt-scan.c
|
|||
krt-scan.h
|
||||
#endif
|
||||
sysio.h
|
||||
syspriv.h
|
||||
|
|
62
sysdep/linux/syspriv.h
Normal file
62
sysdep/linux/syspriv.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
#include <sys/prctl.h>
|
||||
#include <linux/capability.h>
|
||||
|
||||
#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");
|
||||
}
|
|
@ -8,11 +8,15 @@
|
|||
|
||||
#undef LOCAL_DEBUG
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/lists.h"
|
||||
|
@ -58,6 +62,29 @@ async_dump(void)
|
|||
debug("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dropping privileges
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_RESTRICTED_PRIVILEGES
|
||||
#include "lib/syspriv.h"
|
||||
#else
|
||||
|
||||
static inline void
|
||||
drop_uid(uid_t uid)
|
||||
{
|
||||
die("Cannot change user on this platform");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
drop_gid(gid_t gid)
|
||||
{
|
||||
if (setgid(gid) < 0)
|
||||
die("setgid: %m");
|
||||
}
|
||||
|
||||
/*
|
||||
* Reading the Configuration
|
||||
*/
|
||||
|
@ -444,14 +471,16 @@ signal_init(void)
|
|||
* Parsing of command-line arguments
|
||||
*/
|
||||
|
||||
static char *opt_list = "c:dD:ps:";
|
||||
static char *opt_list = "c:dD:ps:u:g:";
|
||||
static int parse_and_exit;
|
||||
char *bird_name;
|
||||
static char *use_user;
|
||||
static char *use_group;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>]\n", bird_name);
|
||||
fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-u <user>] [-g <group>]\n", bird_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -469,6 +498,44 @@ get_bird_name(char *s, char *def)
|
|||
return t+1;
|
||||
}
|
||||
|
||||
static inline uid_t
|
||||
get_uid(const char *s)
|
||||
{
|
||||
struct passwd *pw;
|
||||
char *endptr;
|
||||
|
||||
errno = 0;
|
||||
long int rv = strtol(s, &endptr, 10);
|
||||
|
||||
if (!errno && !*endptr)
|
||||
return rv;
|
||||
|
||||
pw = getpwnam(s);
|
||||
if (!pw)
|
||||
die("Cannot find user '%s'", s);
|
||||
|
||||
return pw->pw_uid;
|
||||
}
|
||||
|
||||
static inline gid_t
|
||||
get_gid(const char *s)
|
||||
{
|
||||
struct group *gr;
|
||||
char *endptr;
|
||||
|
||||
errno = 0;
|
||||
long int rv = strtol(s, &endptr, 10);
|
||||
|
||||
if (!errno && !*endptr)
|
||||
return rv;
|
||||
|
||||
gr = getgrnam(s);
|
||||
if (!gr)
|
||||
die("Cannot find group '%s'", s);
|
||||
|
||||
return gr->gr_gid;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_args(int argc, char **argv)
|
||||
{
|
||||
|
@ -504,6 +571,12 @@ parse_args(int argc, char **argv)
|
|||
case 's':
|
||||
path_control_socket = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
use_user = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
use_group = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
@ -528,6 +601,12 @@ main(int argc, char **argv)
|
|||
log_init_debug("");
|
||||
log_switch(debug_flag, NULL, NULL);
|
||||
|
||||
if (use_group)
|
||||
drop_gid(get_gid(use_group));
|
||||
|
||||
if (use_user)
|
||||
drop_uid(get_uid(use_user));
|
||||
|
||||
if (!parse_and_exit)
|
||||
test_old_bird(path_control_socket);
|
||||
|
||||
|
|
Loading…
Reference in a new issue