2 * Copyright (C) 2015 Etienne CHAMPETIER <champetier.etienne@gmail.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include <sys/prctl.h>
18 #include <libubox/blobmsg.h>
19 #include <libubox/blobmsg_json.h>
22 #include "../capabilities-names.h"
23 #include "capabilities.h"
25 static int find_capabilities(const char *name
)
29 for (i
= 0; i
<= CAP_LAST_CAP
; i
++)
30 if (capabilities_names
[i
] && !strcmp(capabilities_names
[i
], name
))
36 int drop_capabilities(const char *file
)
43 static const struct blobmsg_policy policy
[__CAP_MAX
] = {
44 [CAP_KEEP
] = { .name
= "cap.keep", .type
= BLOBMSG_TYPE_ARRAY
},
45 [CAP_DROP
] = { .name
= "cap.drop", .type
= BLOBMSG_TYPE_ARRAY
},
47 struct blob_buf b
= { 0 };
48 struct blob_attr
*tb
[__CAP_MAX
];
49 struct blob_attr
*cur
;
52 uint64_t capdrop
= 0LLU;
54 DEBUG("dropping capabilities\n");
57 if (!blobmsg_add_json_from_file(&b
, file
)) {
58 ERROR("failed to load %s\n", file
);
62 blobmsg_parse(policy
, __CAP_MAX
, tb
, blob_data(b
.head
), blob_len(b
.head
));
63 if (!tb
[CAP_KEEP
] && !tb
[CAP_DROP
]) {
64 ERROR("failed to parse %s\n", file
);
68 blobmsg_for_each_attr(cur
, tb
[CAP_KEEP
], rem
) {
69 name
= blobmsg_get_string(cur
);
71 ERROR("invalid capability name in cap.keep\n");
74 cap
= find_capabilities(name
);
76 ERROR("unknown capability %s in cap.keep\n", name
);
79 capdrop
|= (1LLU << cap
);
82 if (capdrop
== 0LLU) {
83 DEBUG("cap.keep empty -> only dropping capabilities from cap.drop (blacklist)\n");
84 capdrop
= 0xffffffffffffffffLLU
;
86 DEBUG("cap.keep has at least one capability -> dropping every capabilities not in cap.keep (whitelist)\n");
89 blobmsg_for_each_attr(cur
, tb
[CAP_DROP
], rem
) {
90 name
= blobmsg_get_string(cur
);
92 ERROR("invalid capability name in cap.drop\n");
95 cap
= find_capabilities(name
);
97 ERROR("unknown capability %s in cap.drop\n", name
);
100 capdrop
&= ~(1LLU << cap
);
103 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
104 if ( (capdrop
& (1LLU << cap
)) == 0) {
105 DEBUG("dropping capability %s (%d)\n", capabilities_names
[cap
], cap
);
106 if (prctl(PR_CAPBSET_DROP
, cap
, 0, 0, 0)) {
107 ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s\n", cap
, strerror(errno
));
111 DEBUG("keeping capability %s (%d)\n", capabilities_names
[cap
], cap
);