From e8b89a610443f32b901801668cbae634e13f3e68 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 15 May 2011 16:29:44 +0200 Subject: [PATCH] Update and document the privilege restriction. --- doc/bird.sgml | 32 ++++++++++++++++++++++++++++ sysdep/linux/syspriv.h | 5 +++++ sysdep/unix/main.c | 47 ++++++++++++++++++++++++++++-------------- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index 31b2c03f..01e70e82 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -145,10 +145,42 @@ options. The most important ones are: -s use given filename for a socket for communications with the client, default is /var/run/bird.ctl. + + -u + drop privileges and use that user ID, see the next section for details. + + -g + use that group ID, see the next section for details.

BIRD writes messages about its work to log files or syslog (according to config). +Privileges + +

BIRD, as a routing daemon, uses several privileged operations (like +setting routing table and using raw sockets). Traditionally, BIRD is +executed and runs with root privileges, which may be prone to security +problems. The recommended way is to use a privilege restriction +(options A nonprivileged user (as an argument to Finally, there is a possibility to use external tools to run BIRD in +an environment with restricted privileges. This may need some +configuration, but it is generally easy -- BIRD needs just the +standard library, privileges to read the config file and create the +control socket and the CAP_NET_* capabilities. + About routing tables

BIRD has one or more routing tables which may or may not be diff --git a/sysdep/linux/syspriv.h b/sysdep/linux/syspriv.h index bfe19ac3..b2cdde85 100644 --- a/sysdep/linux/syspriv.h +++ b/sysdep/linux/syspriv.h @@ -48,15 +48,20 @@ drop_uid(uid_t uid) CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_RAW); + /* change effective user ID to be able to switch to that + user ID completely after dropping CAP_SETUID */ if (seteuid(uid) < 0) die("seteuid: %m"); + /* restrict the capabilities */ if (set_capabilities(caps) < 0) die("capset: %m"); + /* keep the capabilities after dropping root ID */ if (prctl(PR_SET_KEEPCAPS, 1) < 0) die("prctl: %m"); + /* completely switch to the unprivileged user ID */ if (setresuid(uid, uid, uid) < 0) die("setresuid: %m"); } diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 744062b4..610d207d 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -383,7 +383,7 @@ cli_connect(sock *s, int size UNUSED) } static void -cli_init_unix(void) +cli_init_unix(uid_t use_uid, gid_t use_gid) { sock *s; @@ -393,6 +393,13 @@ cli_init_unix(void) s->rx_hook = cli_connect; s->rbsize = 1024; sk_open_unix(s, path_control_socket); + + if (use_uid || use_gid) + if (chown(path_control_socket, use_uid, use_gid) < 0) + die("chown: %m"); + + if (chmod(path_control_socket, 0660) < 0) + die("chmod: %m"); } /* @@ -503,9 +510,13 @@ get_uid(const char *s) { struct passwd *pw; char *endptr; - + long int rv; + + if (!s) + return 0; + errno = 0; - long int rv = strtol(s, &endptr, 10); + rv = strtol(s, &endptr, 10); if (!errno && !*endptr) return rv; @@ -522,9 +533,13 @@ get_gid(const char *s) { struct group *gr; char *endptr; + long int rv; + + if (!s) + return 0; errno = 0; - long int rv = strtol(s, &endptr, 10); + rv = strtol(s, &endptr, 10); if (!errno && !*endptr) return rv; @@ -601,24 +616,26 @@ 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); - - DBG("Initializing.\n"); resource_init(); olock_init(); io_init(); rt_init(); if_init(); + uid_t use_uid = get_uid(use_user); + gid_t use_gid = get_gid(use_group); + if (!parse_and_exit) - cli_init_unix(); + { + test_old_bird(path_control_socket); + cli_init_unix(use_uid, use_gid); + } + + if (use_gid) + drop_gid(use_gid); + + if (use_uid) + drop_uid(use_uid); protos_build(); proto_build(&proto_unix_kernel);