Revision 1bc26957

View differences:

sysdep/cf/README
6 6
CONFIG_MULTIPLE_TABLES	The kernel supports multiple routing tables
7 7
CONFIG_ALL_TABLES_AT_ONCE	Kernel scanner wants to process all tables at once
8 8
CONFIG_MC_PROPER_SRC	Multicast packets have source address according to socket saddr field
9
CONFIG_RESTRICTED_PRIVILEGES	Implements restricted privileges using drop_uid()
9 10

  
10 11
CONFIG_UNIX_IFACE	Use Unix interface scanner
11 12
CONFIG_UNIX_SET		Use Unix route setting
......
19 20
CONFIG_LINUX_MC_MREQN	Linux: Use struct mreqn for multicasting
20 21
CONFIG_LINUX_MC_MREQ	Linux: Use struct mreq
21 22
CONFIG_LINUX_MC_MREQ_BIND	Linux: Use struct mreq and SO_BINDTODEVICE
23

  
sysdep/cf/linux-22.h
17 17
#define CONFIG_LINUX_MC_MREQN
18 18
#define CONFIG_UNIX_DONTROUTE
19 19

  
20
#define CONFIG_RESTRICTED_PRIVILEGES
21

  
20 22
/*
21 23
Link: sysdep/linux/netlink
22 24
Link: sysdep/linux
sysdep/cf/linux-v6.h
19 19
#define CONFIG_MULTIPLE_TABLES
20 20
#define CONFIG_ALL_TABLES_AT_ONCE
21 21

  
22
#define CONFIG_RESTRICTED_PRIVILEGES
23

  
22 24
/*
23 25
Link: sysdep/linux/netlink
24 26
Link: sysdep/linux
sysdep/linux/Modules
3 3
krt-scan.h
4 4
#endif
5 5
sysio.h
6
syspriv.h
sysdep/linux/syspriv.h
1

  
2
#include <sys/prctl.h>
3
#include <linux/capability.h>
4

  
5
#ifndef _LINUX_CAPABILITY_VERSION_3
6
#define _LINUX_CAPABILITY_VERSION_3  0x20080522
7
#define _LINUX_CAPABILITY_U32S_3     2
8
#endif
9

  
10
/* capset() prototype is missing ... */
11
int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
12

  
13
static inline int
14
set_capabilities(u32 caps)
15
{
16
  struct __user_cap_header_struct cap_hdr;
17
  struct __user_cap_data_struct cap_dat[_LINUX_CAPABILITY_U32S_3];
18
  int err;
19

  
20
  cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
21
  cap_hdr.pid = 0;
22

  
23
  memset(cap_dat, 0, sizeof(cap_dat));
24
  cap_dat[0].effective = cap_dat[0].permitted = caps;
25

  
26
  err = capset(&cap_hdr, cap_dat);
27
  if (!err)
28
    return 0;
29

  
30
  /* Kernel may support do not support our version of capability interface.
31
       The last call returned supported version so we just retry it. */
32
  if (errno == EINVAL)
33
  {
34
    err = capset(&cap_hdr, cap_dat);
35
    if (!err)
36
      return 0;
37
  }
38

  
39
  return -1;
40
}
41

  
42
static void
43
drop_uid(uid_t uid)
44
{
45
  u32 caps =
46
    CAP_TO_MASK(CAP_NET_BIND_SERVICE) |
47
    CAP_TO_MASK(CAP_NET_BROADCAST) |
48
    CAP_TO_MASK(CAP_NET_ADMIN) |
49
    CAP_TO_MASK(CAP_NET_RAW);
50

  
51
  if (seteuid(uid) < 0)
52
    die("seteuid: %m");
53

  
54
  if (set_capabilities(caps) < 0)
55
    die("capset: %m");
56

  
57
  if (prctl(PR_SET_KEEPCAPS, 1) < 0)
58
    die("prctl: %m");
59

  
60
  if (setresuid(uid, uid, uid) < 0)
61
    die("setresuid: %m");
62
}
sysdep/unix/main.c
8 8

  
9 9
#undef LOCAL_DEBUG
10 10

  
11
#define _GNU_SOURCE 1
12

  
11 13
#include <stdio.h>
12 14
#include <stdlib.h>
13 15
#include <fcntl.h>
14 16
#include <unistd.h>
15 17
#include <signal.h>
18
#include <pwd.h>
19
#include <grp.h>
16 20

  
17 21
#include "nest/bird.h"
18 22
#include "lib/lists.h"
......
59 63
}
60 64

  
61 65
/*
66
 *	Dropping privileges
67
 */
68

  
69
#ifdef CONFIG_RESTRICTED_PRIVILEGES
70
#include "lib/syspriv.h"
71
#else
72

  
73
static inline void
74
drop_uid(uid_t uid)
75
{
76
  die("Cannot change user on this platform");
77
}
78

  
79
#endif
80

  
81
static inline void
82
drop_gid(gid_t gid)
83
{
84
  if (setgid(gid) < 0)
85
    die("setgid: %m");
86
}
87

  
88
/*
62 89
 *	Reading the Configuration
63 90
 */
64 91

  
......
444 471
 *	Parsing of command-line arguments
445 472
 */
446 473

  
447
static char *opt_list = "c:dD:ps:";
474
static char *opt_list = "c:dD:ps:u:g:";
448 475
static int parse_and_exit;
449 476
char *bird_name;
477
static char *use_user;
478
static char *use_group;
450 479

  
451 480
static void
452 481
usage(void)
453 482
{
454
  fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>]\n", bird_name);
483
  fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-u <user>] [-g <group>]\n", bird_name);
455 484
  exit(1);
456 485
}
457 486

  
......
469 498
  return t+1;
470 499
}
471 500

  
501
static inline uid_t
502
get_uid(const char *s)
503
{
504
  struct passwd *pw;
505
  char *endptr;
506
  
507
  errno = 0;
508
  long int rv = strtol(s, &endptr, 10);
509

  
510
  if (!errno && !*endptr)
511
    return rv;
512

  
513
  pw = getpwnam(s);
514
  if (!pw)
515
    die("Cannot find user '%s'", s);
516

  
517
  return pw->pw_uid;
518
}
519

  
520
static inline gid_t
521
get_gid(const char *s)
522
{
523
  struct group *gr;
524
  char *endptr;
525
  
526
  errno = 0;
527
  long int rv = strtol(s, &endptr, 10);
528

  
529
  if (!errno && !*endptr)
530
    return rv;
531

  
532
  gr = getgrnam(s);
533
  if (!gr)
534
    die("Cannot find group '%s'", s);
535

  
536
  return gr->gr_gid;
537
}
538

  
472 539
static void
473 540
parse_args(int argc, char **argv)
474 541
{
......
504 571
      case 's':
505 572
	path_control_socket = optarg;
506 573
	break;
574
      case 'u':
575
	use_user = optarg;
576
	break;
577
      case 'g':
578
	use_group = optarg;
579
	break;
507 580
      default:
508 581
	usage();
509 582
      }
......
528 601
    log_init_debug("");
529 602
  log_switch(debug_flag, NULL, NULL);
530 603

  
604
  if (use_group)
605
    drop_gid(get_gid(use_group));
606

  
607
  if (use_user)
608
    drop_uid(get_uid(use_user));
609

  
531 610
  if (!parse_and_exit)
532 611
    test_old_bird(path_control_socket);
533 612

  

Also available in: Unified diff