chiark / gitweb /
b8002159ec362a549942fb6f390bb952c5f95e51
[elogind.git] / src / shared / capability.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <stdarg.h>
29 #include <ctype.h>
30 #include <sys/capability.h>
31 #include <sys/prctl.h>
32
33 #include "macro.h"
34 #include "capability.h"
35 #include "util.h"
36 #include "log.h"
37
38 int have_effective_cap(int value) {
39         cap_t cap;
40         cap_flag_value_t fv;
41         int r;
42
43         if (!(cap = cap_get_proc()))
44                 return -errno;
45
46         if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
47                 r = -errno;
48         else
49                 r = fv == CAP_SET;
50
51         cap_free(cap);
52         return r;
53 }
54
55 unsigned long cap_last_cap(void) {
56         static __thread unsigned long saved;
57         static __thread bool valid = false;
58         unsigned long p;
59
60         if (valid)
61                 return saved;
62
63         p = (unsigned long) CAP_LAST_CAP;
64
65         if (prctl(PR_CAPBSET_READ, p) < 0) {
66
67                 /* Hmm, look downwards, until we find one that
68                  * works */
69                 for (p--; p > 0; p --)
70                         if (prctl(PR_CAPBSET_READ, p) >= 0)
71                                 break;
72
73         } else {
74
75                 /* Hmm, look upwards, until we find one that doesn't
76                  * work */
77                 for (;; p++)
78                         if (prctl(PR_CAPBSET_READ, p+1) < 0)
79                                 break;
80         }
81
82         saved = p;
83         valid = true;
84
85         return p;
86 }