Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / linux / syspriv.h @ 1bc26957

History | View | Annotate | Download (1.34 KB)

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
}