1*2b3f93eaSMatthew Dillon /*
2*2b3f93eaSMatthew Dillon * Copyright (c) 2023 The DragonFly Project. All rights reserved.
3*2b3f93eaSMatthew Dillon *
4*2b3f93eaSMatthew Dillon * This code is derived from software contributed to The DragonFly Project
5*2b3f93eaSMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
6*2b3f93eaSMatthew Dillon *
7*2b3f93eaSMatthew Dillon * Redistribution and use in source and binary forms, with or without
8*2b3f93eaSMatthew Dillon * modification, are permitted provided that the following conditions
9*2b3f93eaSMatthew Dillon * are met:
10*2b3f93eaSMatthew Dillon *
11*2b3f93eaSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
12*2b3f93eaSMatthew Dillon * notice, this list of conditions and the following disclaimer.
13*2b3f93eaSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
14*2b3f93eaSMatthew Dillon * notice, this list of conditions and the following disclaimer in
15*2b3f93eaSMatthew Dillon * the documentation and/or other materials provided with the
16*2b3f93eaSMatthew Dillon * distribution.
17*2b3f93eaSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
18*2b3f93eaSMatthew Dillon * contributors may be used to endorse or promote products derived
19*2b3f93eaSMatthew Dillon * from this software without specific, prior written permission.
20*2b3f93eaSMatthew Dillon *
21*2b3f93eaSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*2b3f93eaSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*2b3f93eaSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*2b3f93eaSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25*2b3f93eaSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*2b3f93eaSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*2b3f93eaSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*2b3f93eaSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*2b3f93eaSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*2b3f93eaSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*2b3f93eaSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*2b3f93eaSMatthew Dillon * SUCH DAMAGE.
33*2b3f93eaSMatthew Dillon */
34*2b3f93eaSMatthew Dillon /*
35*2b3f93eaSMatthew Dillon * setcaps - Set capability restrictions on the parent process of this
36*2b3f93eaSMatthew Dillon * program (usually a shell).
37*2b3f93eaSMatthew Dillon */
38*2b3f93eaSMatthew Dillon #include <sys/types.h>
39*2b3f93eaSMatthew Dillon #include <sys/caps.h>
40*2b3f93eaSMatthew Dillon #include <errno.h>
41*2b3f93eaSMatthew Dillon #include <stdio.h>
42*2b3f93eaSMatthew Dillon #include <stdlib.h>
43*2b3f93eaSMatthew Dillon #include <string.h>
44*2b3f93eaSMatthew Dillon #include <unistd.h>
45*2b3f93eaSMatthew Dillon
46*2b3f93eaSMatthew Dillon __SYSCAP_ALLSTRINGS;
47*2b3f93eaSMatthew Dillon
48*2b3f93eaSMatthew Dillon static void printallcaps(void);
49*2b3f93eaSMatthew Dillon static void listcaps(void);
50*2b3f93eaSMatthew Dillon
51*2b3f93eaSMatthew Dillon int
main(int ac,char ** av)52*2b3f93eaSMatthew Dillon main(int ac, char **av)
53*2b3f93eaSMatthew Dillon {
54*2b3f93eaSMatthew Dillon int quietopt = 0;
55*2b3f93eaSMatthew Dillon int c;
56*2b3f93eaSMatthew Dillon int i;
57*2b3f93eaSMatthew Dillon int j;
58*2b3f93eaSMatthew Dillon int estatus = 0;
59*2b3f93eaSMatthew Dillon int noargs = 1;
60*2b3f93eaSMatthew Dillon
61*2b3f93eaSMatthew Dillon while ((c = getopt(ac, av, "plqh")) != -1) {
62*2b3f93eaSMatthew Dillon noargs = 0;
63*2b3f93eaSMatthew Dillon switch(c) {
64*2b3f93eaSMatthew Dillon case 'p':
65*2b3f93eaSMatthew Dillon printallcaps();
66*2b3f93eaSMatthew Dillon break;
67*2b3f93eaSMatthew Dillon case 'l':
68*2b3f93eaSMatthew Dillon listcaps();
69*2b3f93eaSMatthew Dillon break;
70*2b3f93eaSMatthew Dillon case 'q':
71*2b3f93eaSMatthew Dillon quietopt = 1;
72*2b3f93eaSMatthew Dillon break;
73*2b3f93eaSMatthew Dillon case 'h':
74*2b3f93eaSMatthew Dillon default:
75*2b3f93eaSMatthew Dillon if (c != 'h')
76*2b3f93eaSMatthew Dillon fprintf(stderr, "Bad option: -%c\n", c);
77*2b3f93eaSMatthew Dillon fprintf(stderr, "setcaps [-p] [-l] caps...\n");
78*2b3f93eaSMatthew Dillon fprintf(stderr, " -p - list available caps\n");
79*2b3f93eaSMatthew Dillon fprintf(stderr, " -l - list current caps\n");
80*2b3f93eaSMatthew Dillon fprintf(stderr, " -q - ignore unknown caps\n");
81*2b3f93eaSMatthew Dillon fprintf(stderr, " caps[:es] - set specific flags\n");
82*2b3f93eaSMatthew Dillon fprintf(stderr, " If no args, current caps are "
83*2b3f93eaSMatthew Dillon "listed\n");
84*2b3f93eaSMatthew Dillon if (c != 'h')
85*2b3f93eaSMatthew Dillon exit(1);
86*2b3f93eaSMatthew Dillon exit(0);
87*2b3f93eaSMatthew Dillon }
88*2b3f93eaSMatthew Dillon }
89*2b3f93eaSMatthew Dillon ac -= optind;
90*2b3f93eaSMatthew Dillon av += optind;
91*2b3f93eaSMatthew Dillon
92*2b3f93eaSMatthew Dillon for (j = 0; j < ac; ++j) {
93*2b3f93eaSMatthew Dillon char *which;
94*2b3f93eaSMatthew Dillon char *scan;
95*2b3f93eaSMatthew Dillon int res;
96*2b3f93eaSMatthew Dillon int flags = __SYSCAP_SELF | __SYSCAP_EXEC;
97*2b3f93eaSMatthew Dillon int found = 0;
98*2b3f93eaSMatthew Dillon
99*2b3f93eaSMatthew Dillon noargs = 0;
100*2b3f93eaSMatthew Dillon
101*2b3f93eaSMatthew Dillon which = av[j];
102*2b3f93eaSMatthew Dillon if ((scan = strchr(which, ':')) != NULL) {
103*2b3f93eaSMatthew Dillon *scan++ = 0;
104*2b3f93eaSMatthew Dillon flags = 0;
105*2b3f93eaSMatthew Dillon while (*scan) {
106*2b3f93eaSMatthew Dillon switch (*scan) {
107*2b3f93eaSMatthew Dillon case 's':
108*2b3f93eaSMatthew Dillon flags |= __SYSCAP_SELF;
109*2b3f93eaSMatthew Dillon break;
110*2b3f93eaSMatthew Dillon case 'e':
111*2b3f93eaSMatthew Dillon flags |= __SYSCAP_EXEC;
112*2b3f93eaSMatthew Dillon break;
113*2b3f93eaSMatthew Dillon default:
114*2b3f93eaSMatthew Dillon fprintf(stderr, "unknown flag %s:%c\n",
115*2b3f93eaSMatthew Dillon which, *scan);
116*2b3f93eaSMatthew Dillon break;
117*2b3f93eaSMatthew Dillon }
118*2b3f93eaSMatthew Dillon ++scan;
119*2b3f93eaSMatthew Dillon }
120*2b3f93eaSMatthew Dillon }
121*2b3f93eaSMatthew Dillon for (i = 0; i < __SYSCAP_COUNT; ++i) {
122*2b3f93eaSMatthew Dillon const char *ptr;
123*2b3f93eaSMatthew Dillon
124*2b3f93eaSMatthew Dillon ptr = SyscapAllStrings[i / 16][i & 15];
125*2b3f93eaSMatthew Dillon if (ptr == NULL || strcmp(ptr, which) != 0)
126*2b3f93eaSMatthew Dillon continue;
127*2b3f93eaSMatthew Dillon found = 1;
128*2b3f93eaSMatthew Dillon res = syscap_set(i | __SYSCAP_INPARENT, flags, NULL, 0);
129*2b3f93eaSMatthew Dillon if (res < 0) {
130*2b3f93eaSMatthew Dillon fprintf(stderr, "%s: %s\n",
131*2b3f93eaSMatthew Dillon which, strerror(errno));
132*2b3f93eaSMatthew Dillon estatus = 1;
133*2b3f93eaSMatthew Dillon } else {
134*2b3f93eaSMatthew Dillon printf("%s: ", which);
135*2b3f93eaSMatthew Dillon if (res & __SYSCAP_EXEC)
136*2b3f93eaSMatthew Dillon printf(" on-exec");
137*2b3f93eaSMatthew Dillon if (res & __SYSCAP_SELF)
138*2b3f93eaSMatthew Dillon printf(" on-self");
139*2b3f93eaSMatthew Dillon printf("\n");
140*2b3f93eaSMatthew Dillon }
141*2b3f93eaSMatthew Dillon }
142*2b3f93eaSMatthew Dillon if (found == 0 && quietopt == 0) {
143*2b3f93eaSMatthew Dillon printf("%s: not-found\n", which);
144*2b3f93eaSMatthew Dillon }
145*2b3f93eaSMatthew Dillon }
146*2b3f93eaSMatthew Dillon if (noargs)
147*2b3f93eaSMatthew Dillon listcaps();
148*2b3f93eaSMatthew Dillon
149*2b3f93eaSMatthew Dillon return estatus;
150*2b3f93eaSMatthew Dillon }
151*2b3f93eaSMatthew Dillon
152*2b3f93eaSMatthew Dillon static void
printallcaps(void)153*2b3f93eaSMatthew Dillon printallcaps(void)
154*2b3f93eaSMatthew Dillon {
155*2b3f93eaSMatthew Dillon const char *ptr;
156*2b3f93eaSMatthew Dillon int i;
157*2b3f93eaSMatthew Dillon
158*2b3f93eaSMatthew Dillon for (i = 0; i < __SYSCAP_COUNT; ++i) {
159*2b3f93eaSMatthew Dillon if ((ptr = SyscapAllStrings[i / 16][i & 15]) != NULL) {
160*2b3f93eaSMatthew Dillon printf("0x%04x %s\n", i, ptr);
161*2b3f93eaSMatthew Dillon }
162*2b3f93eaSMatthew Dillon }
163*2b3f93eaSMatthew Dillon }
164*2b3f93eaSMatthew Dillon
165*2b3f93eaSMatthew Dillon static void
listcaps(void)166*2b3f93eaSMatthew Dillon listcaps(void)
167*2b3f93eaSMatthew Dillon {
168*2b3f93eaSMatthew Dillon int i;
169*2b3f93eaSMatthew Dillon
170*2b3f93eaSMatthew Dillon for (i = 0; i < __SYSCAP_COUNT; ++i) {
171*2b3f93eaSMatthew Dillon const char *ptr;
172*2b3f93eaSMatthew Dillon int res;
173*2b3f93eaSMatthew Dillon
174*2b3f93eaSMatthew Dillon res = syscap_get(i | __SYSCAP_INPARENT, NULL, 0);
175*2b3f93eaSMatthew Dillon if (res < 0)
176*2b3f93eaSMatthew Dillon break;
177*2b3f93eaSMatthew Dillon if (res) {
178*2b3f93eaSMatthew Dillon if ((ptr = SyscapAllStrings[i / 16][i & 15]) != NULL) {
179*2b3f93eaSMatthew Dillon printf("%-15s", ptr);
180*2b3f93eaSMatthew Dillon } else {
181*2b3f93eaSMatthew Dillon printf("0x%04x ", res);
182*2b3f93eaSMatthew Dillon }
183*2b3f93eaSMatthew Dillon if (res & __SYSCAP_EXEC)
184*2b3f93eaSMatthew Dillon printf(" on-exec");
185*2b3f93eaSMatthew Dillon if (res & __SYSCAP_SELF)
186*2b3f93eaSMatthew Dillon printf(" on-self");
187*2b3f93eaSMatthew Dillon printf("\n");
188*2b3f93eaSMatthew Dillon }
189*2b3f93eaSMatthew Dillon }
190*2b3f93eaSMatthew Dillon }
191