blob: 05d0c475d73b7b1307837081bb71b988f0a7a6c3 [file] [log] [blame]
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -04001/* Copyright (C) 2017 The Android Open Source Project
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "system.h"
17
18#include <errno.h>
19#include <fcntl.h>
20#include <net/if.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <string.h>
24#include <sys/ioctl.h>
25#include <sys/prctl.h>
26#include <sys/socket.h>
27#include <sys/stat.h>
28#include <unistd.h>
29
30#include "util.h"
31
32#ifdef HAVE_SECUREBITS_H
33#include <linux/securebits.h>
34#else
35#define SECURE_ALL_BITS 0x55
36#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
37#endif
38/* For kernels < 4.3. */
39#define OLD_SECURE_ALL_BITS 0x15
40#define OLD_SECURE_ALL_LOCKS (OLD_SECURE_ALL_BITS << 1)
41
42/*
43 * Assert the value of SECURE_ALL_BITS at compile-time.
44 * Brillo devices are currently compiled against 4.4 kernel headers. Kernel 4.3
45 * added a new securebit.
46 * When a new securebit is added, the new SECURE_ALL_BITS mask will return EPERM
47 * when used on older kernels. The compile-time assert will catch this situation
48 * at compile time.
49 */
50#ifdef __BRILLO__
51_Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55.");
52#endif
53
54int lock_securebits(void)
55{
56 /*
57 * Kernels 4.3+ define a new securebit (SECURE_NO_CAP_AMBIENT_RAISE),
58 * so using the SECURE_ALL_BITS and SECURE_ALL_LOCKS masks from
59 * newer kernel headers will return EPERM on older kernels. Detect this,
60 * and retry with the right mask for older (2.6.26-4.2) kernels.
61 */
62 int securebits_ret =
63 prctl(PR_SET_SECUREBITS, SECURE_ALL_BITS | SECURE_ALL_LOCKS);
64 if (securebits_ret < 0) {
65 if (errno == EPERM) {
66 /* Possibly running on kernel < 4.3. */
67 securebits_ret =
68 prctl(PR_SET_SECUREBITS,
69 OLD_SECURE_ALL_BITS | OLD_SECURE_ALL_LOCKS);
70 }
71 }
72 if (securebits_ret < 0) {
73 pwarn("prctl(PR_SET_SECUREBITS) failed");
74 return -1;
75 }
76
77 return 0;
78}
79
80int write_proc_file(pid_t pid, const char *content, const char *basename)
81{
82 int fd, ret;
83 size_t sz, len;
84 ssize_t written;
85 char filename[32];
86
87 sz = sizeof(filename);
88 ret = snprintf(filename, sz, "/proc/%d/%s", pid, basename);
89 if (ret < 0 || (size_t)ret >= sz) {
90 warn("failed to generate %s filename", basename);
91 return -1;
92 }
93
94 fd = open(filename, O_WRONLY | O_CLOEXEC);
95 if (fd < 0) {
96 pwarn("failed to open '%s'", filename);
97 return -errno;
98 }
99
100 len = strlen(content);
101 written = write(fd, content, len);
102 if (written < 0) {
103 pwarn("failed to write '%s'", filename);
104 return -1;
105 }
106
107 if ((size_t)written < len) {
108 warn("failed to write %zu bytes to '%s'", len, filename);
109 return -1;
110 }
111 close(fd);
112 return 0;
113}
114
115/*
116 * We specifically do not use cap_valid() as that only tells us the last
117 * valid cap we were *compiled* against (i.e. what the version of kernel
118 * headers says). If we run on a different kernel version, then it's not
119 * uncommon for that to be less (if an older kernel) or more (if a newer
120 * kernel).
121 * Normally, we suck up the answer via /proc. On Android, not all processes are
122 * guaranteed to be able to access '/proc/sys/kernel/cap_last_cap' so we
123 * programmatically find the value by calling prctl(PR_CAPBSET_READ).
124 */
125unsigned int get_last_valid_cap(void)
126{
127 unsigned int last_valid_cap = 0;
128 if (is_android()) {
129 for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0;
130 ++last_valid_cap)
131 ;
132
133 /* |last_valid_cap| will be the first failing value. */
134 if (last_valid_cap > 0) {
135 last_valid_cap--;
136 }
137 } else {
138 const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
139 FILE *fp = fopen(cap_file, "re");
140 if (fscanf(fp, "%u", &last_valid_cap) != 1)
141 pdie("fscanf(%s)", cap_file);
142 fclose(fp);
143 }
144 return last_valid_cap;
145}
146
147int config_net_loopback(void)
148{
149 const char ifname[] = "lo";
150 int sock;
151 struct ifreq ifr;
152
153 /* Make sure people don't try to add really long names. */
154 _Static_assert(sizeof(ifname) <= IFNAMSIZ, "interface name too long");
155
156 sock = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
157 if (sock < 0) {
158 pwarn("socket(AF_LOCAL) failed");
159 return -1;
160 }
161
162 /*
163 * Do the equiv of `ip link set up lo`. The kernel will assign
164 * IPv4 (127.0.0.1) & IPv6 (::1) addresses automatically!
165 */
166 strcpy(ifr.ifr_name, ifname);
167 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
168 pwarn("ioctl(SIOCGIFFLAGS) failed");
169 return -1;
170 }
171
172 /* The kernel preserves ifr.ifr_name for use. */
173 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
174 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
175 pwarn("ioctl(SIOCSIFFLAGS) failed");
176 return -1;
177 }
178
179 close(sock);
180 return 0;
181}
182
183int setup_pipe_end(int fds[2], size_t index)
184{
185 if (index > 1)
186 return -1;
187
188 close(fds[1 - index]);
189 return fds[index];
190}
191
192int setup_and_dupe_pipe_end(int fds[2], size_t index, int fd)
193{
194 if (index > 1)
195 return -1;
196
197 close(fds[1 - index]);
198 /* dup2(2) the corresponding end of the pipe into |fd|. */
199 return dup2(fds[index], fd);
200}
201
202int write_pid_to_path(pid_t pid, const char *path)
203{
204 FILE *fp = fopen(path, "w");
205
206 if (!fp) {
207 pwarn("failed to open '%s'", path);
208 return -errno;
209 }
210 if (fprintf(fp, "%d\n", (int)pid) < 0) {
211 /* fprintf(3) does not set errno on failure. */
212 warn("fprintf(%s) failed", path);
213 return -1;
214 }
215 if (fclose(fp)) {
216 pwarn("fclose(%s) failed", path);
217 return -errno;
218 }
219
220 return 0;
221}
222
223/*
224 * setup_mount_destination: Ensures the mount target exists.
225 * Creates it if needed and possible.
226 */
227int setup_mount_destination(const char *source, const char *dest, uid_t uid,
228 uid_t gid)
229{
230 int rc;
231 struct stat st_buf;
232
233 rc = stat(dest, &st_buf);
234 if (rc == 0) /* destination exists */
235 return 0;
236
237 /*
238 * Try to create the destination.
239 * Either make a directory or touch a file depending on the source type.
240 * If the source doesn't exist, assume it is a filesystem type such as
241 * "tmpfs" and create a directory to mount it on.
242 */
243 rc = stat(source, &st_buf);
244 if (rc || S_ISDIR(st_buf.st_mode) || S_ISBLK(st_buf.st_mode)) {
245 if (mkdir(dest, 0700))
246 return -errno;
247 } else {
248 int fd = open(dest, O_RDWR | O_CREAT, 0700);
249 if (fd < 0)
250 return -errno;
251 close(fd);
252 }
253 return chown(dest, uid, gid);
254}