]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/utils.h
Merge pull request #3956 from brauner/2021-08-27.list
[mirror_lxc.git] / src / lxc / utils.h
CommitLineData
cc73685d
CB
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
f1a4a029
ÇO
3#ifndef __LXC_UTILS_H
4#define __LXC_UTILS_H
0ad19a3f 5
c6868a1f
CB
6/* Properly support loop devices on 32bit systems. */
7#define _FILE_OFFSET_BITS 64
8
6a44839f 9#include <errno.h>
c6868a1f 10#include <linux/loop.h>
5038d11a 11#include <linux/types.h>
d38dd64a
CB
12#include <stdarg.h>
13#include <stdbool.h>
14#include <stdio.h>
4a6af918 15#include <string.h>
ec346ea1 16#include <sys/syscall.h>
c797a220 17#include <sys/types.h>
a035c53a 18#include <sys/vfs.h>
d38dd64a 19#include <unistd.h>
f749d524 20
5f1b0986 21#include "compiler.h"
37ef15bb 22#include "file_utils.h"
4295c5de 23#include "initutils.h"
279c45ee 24#include "macro.h"
4110345b 25#include "memory_utils.h"
f40988c7 26#include "process_utils.h"
37ef15bb 27#include "string_utils.h"
b07511df 28
60bf62d4 29/* returns 1 on success, 0 if there were any failures */
5f1b0986
CB
30__hidden extern int lxc_rmdir_onedev(const char *path, const char *exclude);
31__hidden extern int get_u16(unsigned short *val, const char *arg, int base);
32__hidden extern int mkdir_p(const char *dir, mode_t mode);
33__hidden extern char *get_rundir(void);
9e60f51d 34
6a44839f
DE
35/* Define getline() if missing from the C library */
36#ifndef HAVE_GETLINE
37#ifdef HAVE_FGETLN
38#include <../include/getline.h>
39#endif
40#endif
41
b499121f
CB
42static inline int lxc_set_cloexec(int fd)
43{
44 return fcntl(fd, F_SETFD, FD_CLOEXEC);
45}
46
ebf3a6af
CB
47/*
48 * Struct to carry child pid from lxc_popen() to lxc_pclose(). Not an opaque
49 * struct to allow direct access to the underlying FILE without additional
50 * wrappers.
ebec9176
AM
51 */
52struct lxc_popen_FILE {
8bd8018e 53 int pipe;
ebec9176
AM
54 FILE *f;
55 pid_t child_pid;
56};
57
58/* popen(command, "re") replacement that restores default signal mask
59 * via sigprocmask(2) (unblocks all signals) after fork(2) but prior to calling exec(3).
60 * In short, popen(command, "re") does pipe() + fork() + exec()
61 * while lxc_popen(command) does pipe() + fork() + sigprocmask() + exec().
ebec9176
AM
62 * Returns pointer to struct lxc_popen_FILE, that should be freed with lxc_pclose().
63 * On error returns NULL.
64 */
5f1b0986 65__hidden extern struct lxc_popen_FILE *lxc_popen(const char *command);
ebec9176
AM
66
67/* pclose() replacement to be used on struct lxc_popen_FILE *,
68 * returned by lxc_popen().
69 * Waits for associated process to terminate, returns its exit status and
70 * frees resources, pointed to by struct lxc_popen_FILE *.
ebec9176 71 */
5f1b0986 72__hidden extern int lxc_pclose(struct lxc_popen_FILE *fp);
ebec9176 73
55022530
CB
74static inline void __auto_lxc_pclose__(struct lxc_popen_FILE **f)
75{
76 if (*f)
77 lxc_pclose(*f);
78}
79#define __do_lxc_pclose __attribute__((__cleanup__(__auto_lxc_pclose__)))
80
9be53773
SH
81/*
82 * wait on a child we forked
83 */
5f1b0986
CB
84__hidden extern int wait_for_pid(pid_t pid);
85__hidden extern int lxc_wait_for_pid_status(pid_t pid);
86__hidden extern int wait_for_pidfd(int pidfd);
9be53773 87
fa2bb6ba 88#if HAVE_OPENSSL
5f1b0986 89__hidden extern int sha1sum_file(char *fnam, unsigned char *md_value, unsigned int *md_len);
3ce74686 90#endif
92f023dc 91
1a0e70ac 92/* initialize rand with urandom */
5f1b0986 93__hidden extern int randseed(bool);
052616eb 94
477aa378
SH
95/* are we unprivileged with respect to our namespaces */
96inline static bool am_guest_unpriv(void) {
97 return geteuid() != 0;
98}
99
100/* are we unprivileged with respect to init_user_ns */
5384e99d 101inline static bool am_host_unpriv(void)
4692c01a 102{
4110345b 103 __do_fclose FILE *f = NULL;
4692c01a
TA
104 uid_t user, host, count;
105 int ret;
106
107 if (geteuid() != 0)
108 return true;
109
110 /* Now: are we in a user namespace? Because then we're also
111 * unprivileged.
112 */
4110345b
CB
113 f = fopen("/proc/self/uid_map", "re");
114 if (!f)
4692c01a 115 return false;
4692c01a
TA
116
117 ret = fscanf(f, "%u %u %u", &user, &host, &count);
4110345b 118 if (ret != 3)
4692c01a 119 return false;
4692c01a 120
4110345b 121 return user != 0 || host != 0 || count != UINT32_MAX;
1354955b 122}
5d897655
SH
123
124/*
125 * parse /proc/self/uid_map to find what @orig maps to
126 */
5f1b0986 127__hidden extern uid_t get_ns_uid(uid_t orig);
b962868f
CB
128/*
129 * parse /proc/self/gid_map to find what @orig maps to
130 */
5f1b0986 131__hidden extern gid_t get_ns_gid(gid_t orig);
c476bdce 132
5f1b0986 133__hidden extern bool dir_exists(const char *path);
93c379f0
ÇO
134
135#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
5f1b0986
CB
136__hidden extern uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
137
138__hidden extern bool is_shared_mountpoint(const char *path);
139__hidden extern int detect_shared_rootfs(void);
140__hidden extern bool detect_ramfs_rootfs(void);
141__hidden extern char *on_path(const char *cmd, const char *rootfs);
5f1b0986
CB
142__hidden extern char *choose_init(const char *rootfs);
143__hidden extern bool switch_to_ns(pid_t pid, const char *ns);
144__hidden extern char *get_template_path(const char *t);
145__hidden extern int safe_mount(const char *src, const char *dest, const char *fstype,
146 unsigned long flags, const void *data, const char *rootfs);
5f1b0986
CB
147__hidden extern int open_devnull(void);
148__hidden extern int set_stdfds(int fd);
149__hidden extern int null_stdfds(void);
150__hidden extern int lxc_preserve_ns(const int pid, const char *ns);
330ae3d3
CB
151
152/* Check whether a signal is blocked by a process. */
5f1b0986 153__hidden extern bool task_blocks_signal(pid_t pid, int signal);
6bc2eafe 154
db2d1af1
CB
155/* Switch to a new uid and gid.
156 * If LXC_INVALID_{G,U}ID is passed then the set{g,u}id() will not be called.
157 */
5f1b0986 158__hidden extern bool lxc_switch_uid_gid(uid_t uid, gid_t gid);
5a7f1dc6 159__hidden extern bool lxc_setgroups(gid_t list[], size_t size);
8dd6f81e 160__hidden extern bool lxc_drop_groups(void);
dbaf55a3 161
c6868a1f 162/* Find an unused loop device and associate it with source. */
5f1b0986 163__hidden extern int lxc_prepare_loop_dev(const char *source, char *loop_dev, int flags);
c6868a1f 164
74251e49
CB
165/* Clear all mounts on a given node.
166 * >= 0 successfully cleared. The number returned is the number of umounts
167 * performed.
168 * < 0 error umounting. Return -errno.
169 */
5f1b0986 170__hidden extern int lxc_unstack_mountpoint(const char *path, bool lazy);
74251e49 171
ea3a694f
CB
172/*
173 * run_command runs a command and collect it's std{err,out} output in buf.
174 *
175 * @param[out] buf The buffer where the commands std{err,out] output will be
176 * read into. If no output was produced, buf will be memset
177 * to 0.
178 * @param[in] buf_size The size of buf. This function will reserve one byte for
179 * \0-termination.
180 * @param[in] child_fn The function to be run in the child process. This
181 * function must exec.
182 * @param[in] args Arguments to be passed to child_fn.
183 */
5f1b0986 184__hidden extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args);
ea3a694f 185
99a8edfc 186/*
187 * run_command runs a command and collect it's std{err,out} output in buf, returns exit status.
188 *
189 * @param[out] buf The buffer where the commands std{err,out] output will be
190 * read into. If no output was produced, buf will be memset
191 * to 0.
192 * @param[in] buf_size The size of buf. This function will reserve one byte for
193 * \0-termination.
194 * @param[in] child_fn The function to be run in the child process. This
195 * function must exec.
196 * @param[in] args Arguments to be passed to child_fn.
197 */
5f1b0986
CB
198__hidden extern int run_command_status(char *buf, size_t buf_size, int (*child_fn)(void *),
199 void *args);
99a8edfc 200
5f1b0986 201__hidden extern bool lxc_nic_exists(char *nic);
0059379f
CB
202
203static inline uint64_t lxc_getpagesize(void)
204{
205 int64_t pgsz;
206
207 pgsz = sysconf(_SC_PAGESIZE);
208 if (pgsz <= 0)
209 pgsz = 1 << 12;
210
211 return pgsz;
212}
a035c53a 213
6222c3f4
CB
214/* If n is not a power of 2 this function will return the next power of 2
215 * greater than that number. Note that this function always returns the *next*
216 * power of 2 *greater* that number not the *nearest*. For example, passing 1025
217 * as argument this function will return 2048 although the closest power of 2
218 * would be 1024.
219 * If the caller passes in 0 they will receive 0 in return since this is invalid
220 * input and 0 is not a power of 2.
221 */
5f1b0986 222__hidden extern uint64_t lxc_find_next_power2(uint64_t n);
6222c3f4 223
1fd0f41e 224/* Set a signal the child process will receive after the parent has died. */
5f1b0986 225__hidden extern int lxc_set_death_signal(int signal, pid_t parent, int parent_status_fd);
5f1b0986 226__hidden extern int lxc_rm_rf(const char *dirname);
5f1b0986 227__hidden extern bool lxc_can_use_pidfd(int pidfd);
1fd0f41e 228
5f1b0986 229__hidden extern int fix_stdio_permissions(uid_t uid);
6aff5157 230
234998b4
CB
231static inline bool uid_valid(uid_t uid)
232{
233 return uid != LXC_INVALID_UID;
234}
235
236static inline bool gid_valid(gid_t gid)
237{
238 return gid != LXC_INVALID_GID;
239}
240
5f1b0986 241__hidden extern bool multiply_overflow(int64_t base, uint64_t mult, int64_t *res);
07f89c1e 242
43535b6d
CB
243__hidden extern int safe_mount_beneath(const char *beneath, const char *src, const char *dst,
244 const char *fstype, unsigned int flags, const void *data);
245__hidden extern int safe_mount_beneath_at(int beneat_fd, const char *src, const char *dst,
246 const char *fstype, unsigned int flags, const void *data);
8cdbef77 247__hidden __lxc_unused int print_r(int fd, const char *path);
65f0afde 248
d329cda7
CB
249static inline int copy_struct_from_client(__u32 server_size, void *dst,
250 __u32 client_size, const void *src)
251{
252 __u32 size = min(server_size, client_size);
253 __u32 rest = min(server_size, client_size) - size;
254
255 /* Deal with trailing bytes. */
256 if (client_size < server_size) {
257 memset(dst + size, 0, rest);
258 } else if (client_size > server_size) {
259 /* TODO: Actually come up with a nice way to test for 0. */
260 return 0;
261 }
262
263 memcpy(dst, src, size);
264 return 0;
265}
266
9ec1d9db
CB
267static inline __u32 copy_struct_to_client(__u32 client_size, void *dst,
268 __u32 server_size, const void *src)
269{
270 __u32 size = min(server_size, client_size);
271 memcpy(dst, src, size);
272 return size;
273}
274
4a6af918
EV
275#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
276static inline int is_in_comm(const char *s)
277{
278 __do_free char *buf = NULL;
279 __do_free char *comm = NULL;
280 size_t buf_size;
281
282 buf = file_to_buf("/proc/self/comm", &buf_size);
283 if (!buf)
284 return -1;
285
286 if (buf_size == 0)
287 return -1;
288
289 comm = malloc(buf_size + 1);
290 if (!comm)
291 return -1;
292 memcpy(comm, buf, buf_size);
293 comm[buf_size] = '\0';
294
295 return strstr(comm, s) != NULL;
296}
297#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
298
5b72de5f 299#endif /* __LXC_UTILS_H */