diff options
Diffstat (limited to 'src/firejail/cpu.c')
-rw-r--r-- | src/firejail/cpu.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c new file mode 100644 index 000000000..633081a3f --- /dev/null +++ b/src/firejail/cpu.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com) | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firejail.h" | ||
21 | #include <sched.h> | ||
22 | |||
23 | // converts a numeric cpu value in the corresponding bit mask | ||
24 | static void set_cpu(const char *str) { | ||
25 | if (strlen(str) == 0) | ||
26 | return; | ||
27 | |||
28 | int val = atoi(str); | ||
29 | if (val < 0 || val >= 32) { | ||
30 | fprintf(stderr, "Error: invalid cpu number. Accepted values are between 0 and 31.\n"); | ||
31 | exit(1); | ||
32 | } | ||
33 | |||
34 | uint32_t mask = 1; | ||
35 | int i; | ||
36 | for (i = 0; i < val; i++, mask <<= 1); | ||
37 | cfg.cpus |= mask; | ||
38 | } | ||
39 | |||
40 | void read_cpu_list(const char *str) { | ||
41 | char *tmp = strdup(str); | ||
42 | if (tmp == NULL) | ||
43 | errExit("strdup"); | ||
44 | |||
45 | char *ptr = tmp; | ||
46 | while (*ptr != '\0') { | ||
47 | if (*ptr == ',' || isdigit(*ptr)) | ||
48 | ; | ||
49 | else { | ||
50 | fprintf(stderr, "Error: invalid cpu list\n"); | ||
51 | exit(1); | ||
52 | } | ||
53 | ptr++; | ||
54 | } | ||
55 | |||
56 | char *start = tmp; | ||
57 | ptr = tmp; | ||
58 | while (*ptr != '\0') { | ||
59 | if (*ptr == ',') { | ||
60 | *ptr = '\0'; | ||
61 | set_cpu(start); | ||
62 | start = ptr + 1; | ||
63 | } | ||
64 | ptr++; | ||
65 | } | ||
66 | set_cpu(start); | ||
67 | free(tmp); | ||
68 | } | ||
69 | |||
70 | void save_cpu(void) { | ||
71 | if (cfg.cpus == 0) | ||
72 | return; | ||
73 | |||
74 | char *fname; | ||
75 | if (asprintf(&fname, "%s/cpu", MNT_DIR) == -1) | ||
76 | errExit("asprintf"); | ||
77 | FILE *fp = fopen(fname, "w"); | ||
78 | if (fp) { | ||
79 | fprintf(fp, "%x\n", cfg.cpus); | ||
80 | fclose(fp); | ||
81 | if (chown(fname, 0, 0) < 0) | ||
82 | errExit("chown"); | ||
83 | } | ||
84 | else { | ||
85 | fprintf(stderr, "Error: cannot save cpu affinity mask\n"); | ||
86 | free(fname); | ||
87 | exit(1); | ||
88 | } | ||
89 | |||
90 | free(fname); | ||
91 | } | ||
92 | |||
93 | void load_cpu(const char *fname) { | ||
94 | if (!fname) | ||
95 | return; | ||
96 | |||
97 | FILE *fp = fopen(fname, "r"); | ||
98 | if (fp) { | ||
99 | unsigned tmp; | ||
100 | int rv = fscanf(fp, "%x", &tmp); | ||
101 | if (rv) | ||
102 | cfg.cpus = (uint32_t) tmp; | ||
103 | fclose(fp); | ||
104 | } | ||
105 | else | ||
106 | fprintf(stderr, "Warning: cannot load cpu affinity mask\n"); | ||
107 | } | ||
108 | |||
109 | void set_cpu_affinity(void) { | ||
110 | // set cpu affinity | ||
111 | cpu_set_t mask; | ||
112 | CPU_ZERO(&mask); | ||
113 | |||
114 | int i; | ||
115 | uint32_t m = 1; | ||
116 | for (i = 0; i < 32; i++, m <<= 1) { | ||
117 | if (cfg.cpus & m) | ||
118 | CPU_SET(i, &mask); | ||
119 | } | ||
120 | |||
121 | if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { | ||
122 | fprintf(stderr, "Warning: cannot set cpu affinity\n"); | ||
123 | fprintf(stderr, " "); | ||
124 | perror("sched_setaffinity"); | ||
125 | } | ||
126 | |||
127 | // verify cpu affinity | ||
128 | cpu_set_t mask2; | ||
129 | CPU_ZERO(&mask2); | ||
130 | if (sched_getaffinity(0, sizeof(mask2), &mask2) == -1) { | ||
131 | fprintf(stderr, "Warning: cannot verify cpu affinity\n"); | ||
132 | fprintf(stderr, " "); | ||
133 | perror("sched_getaffinity"); | ||
134 | } | ||
135 | else { | ||
136 | if (CPU_EQUAL(&mask, &mask2)) | ||
137 | printf("CPU affinity set\n"); | ||
138 | else | ||
139 | printf("CPU affinity not set\n"); | ||
140 | } | ||
141 | } | ||