]> git.ipfire.org Git - thirdparty/util-linux.git/blame - include/mount-api-utils.h
taskset: Accept 0 pid for current process
[thirdparty/util-linux.git] / include / mount-api-utils.h
CommitLineData
faeb1b64
KZ
1/*
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 */
013e0db4
CB
5#ifndef UTIL_LINUX_MOUNT_API_UTILS
6#define UTIL_LINUX_MOUNT_API_UTILS
7
ded434a6
KZ
8#ifdef HAVE_LINUX_MOUNT_H
9#include <sys/mount.h>
10efb9ea 10#include <linux/mount.h>
0033f974 11#include <linux/unistd.h>
ded434a6
KZ
12#include <sys/syscall.h>
13#include <inttypes.h>
14
15/*
16 * File descritors based mount API
17 */
18#ifdef HAVE_MOUNTFD_API
013e0db4 19
013e0db4
CB
20/* Accepted by both open_tree() and mount_setattr(). */
21#ifndef AT_RECURSIVE
1e5381cb 22# define AT_RECURSIVE 0x8000
013e0db4
CB
23#endif
24
25#ifndef OPEN_TREE_CLONE
1e5381cb 26# define OPEN_TREE_CLONE 1
013e0db4
CB
27#endif
28
29#ifndef OPEN_TREE_CLOEXEC
1e5381cb 30# define OPEN_TREE_CLOEXEC O_CLOEXEC
013e0db4
CB
31#endif
32
e087a188 33#if !defined(HAVE_OPEN_TREE) && defined(SYS_open_tree)
013e0db4
CB
34static inline int open_tree(int dfd, const char *filename, unsigned int flags)
35{
e087a188 36 return syscall(SYS_open_tree, dfd, filename, flags);
013e0db4 37}
1e5381cb 38#endif
013e0db4
CB
39
40#ifndef MOVE_MOUNT_F_SYMLINKS
467b0c15 41# define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */
013e0db4
CB
42#endif
43
44#ifndef MOVE_MOUNT_F_AUTOMOUNTS
1e5381cb 45# define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */
013e0db4
CB
46#endif
47
48#ifndef MOVE_MOUNT_F_EMPTY_PATH
1e5381cb 49# define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
013e0db4
CB
50#endif
51
52#ifndef MOVE_MOUNT_T_SYMLINKS
467b0c15 53# define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */
013e0db4
CB
54#endif
55
56#ifndef MOVE_MOUNT_T_AUTOMOUNTS
1e5381cb 57# define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */
013e0db4
CB
58#endif
59
60#ifndef MOVE_MOUNT_T_EMPTY_PATH
1e5381cb 61# define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */
013e0db4
CB
62#endif
63
92ba5cb2 64#ifndef MOVE_MOUNT_SET_GROUP
467b0c15 65# define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */
92ba5cb2
KZ
66#endif
67
013e0db4 68#ifndef MOVE_MOUNT__MASK
1e5381cb 69# define MOVE_MOUNT__MASK 0x00000077
013e0db4
CB
70#endif
71
e087a188 72#if !defined(HAVE_MOVE_MOUNT) && defined(SYS_move_mount)
013e0db4
CB
73static inline int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
74 const char *to_pathname, unsigned int flags)
75{
e087a188 76 return syscall(SYS_move_mount, from_dfd, from_pathname, to_dfd,
013e0db4
CB
77 to_pathname, flags);
78}
1e5381cb 79#endif
013e0db4
CB
80
81#ifndef MOUNT_ATTR_RDONLY
1e5381cb 82# define MOUNT_ATTR_RDONLY 0x00000001
013e0db4
CB
83#endif
84
85#ifndef MOUNT_ATTR_NOSUID
1e5381cb 86# define MOUNT_ATTR_NOSUID 0x00000002
013e0db4
CB
87#endif
88
0749b362
KZ
89#ifndef MOUNT_ATTR_NODEV
90# define MOUNT_ATTR_NODEV 0x00000004
91#endif
92
013e0db4 93#ifndef MOUNT_ATTR_NOEXEC
1e5381cb 94# define MOUNT_ATTR_NOEXEC 0x00000008
013e0db4
CB
95#endif
96
013e0db4 97#ifndef MOUNT_ATTR__ATIME
1e5381cb 98# define MOUNT_ATTR__ATIME 0x00000070
013e0db4
CB
99#endif
100
101#ifndef MOUNT_ATTR_RELATIME
1e5381cb 102# define MOUNT_ATTR_RELATIME 0x00000000
013e0db4
CB
103#endif
104
105#ifndef MOUNT_ATTR_NOATIME
1e5381cb 106# define MOUNT_ATTR_NOATIME 0x00000010
013e0db4
CB
107#endif
108
109#ifndef MOUNT_ATTR_STRICTATIME
1e5381cb 110# define MOUNT_ATTR_STRICTATIME 0x00000020
013e0db4
CB
111#endif
112
9cb77c87
KZ
113#ifndef MOUNT_ATTR_NODIRATIME
114# define MOUNT_ATTR_NODIRATIME 0x00000080
115#endif
116
013e0db4 117#ifndef MOUNT_ATTR_IDMAP
1e5381cb 118# define MOUNT_ATTR_IDMAP 0x00100000
013e0db4
CB
119#endif
120
9cb77c87
KZ
121#ifndef MOUNT_ATTR_NOSYMFOLLOW
122# define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
123#endif
124
1e5381cb 125#ifndef HAVE_STRUCT_MOUNT_ATTR
26788963 126# ifndef MOUNT_ATTR_SIZE_VER0 /* For case mount.h comes from a place invisible for autotools/meson */
43d3c908 127# include <inttypes.h>
013e0db4 128struct mount_attr {
43d3c908
KZ
129 uint64_t attr_set;
130 uint64_t attr_clr;
131 uint64_t propagation;
132 uint64_t userns_fd;
013e0db4 133};
26788963 134# endif
1e5381cb 135#endif
013e0db4 136
e087a188 137#if !defined(HAVE_MOUNT_SETATTR) && defined(SYS_mount_setattr)
013e0db4
CB
138static inline int mount_setattr(int dfd, const char *path, unsigned int flags,
139 struct mount_attr *attr, size_t size)
140{
e087a188 141 return syscall(SYS_mount_setattr, dfd, path, flags, attr, size);
013e0db4 142}
1e5381cb 143#endif
013e0db4 144
0120be6f 145#ifndef HAVE_ENUM_FSCONFIG_COMMAND
26788963 146# ifndef FSOPEN_CLOEXEC /* For case mount.h comes from a place invisible for autotools/meson */
0120be6f
KZ
147enum fsconfig_command {
148 FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
149 FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
150 FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
151 FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
152 FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
153 FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */
154 FSCONFIG_CMD_CREATE = 6, /* Invoke superblock creation */
155 FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
156};
26788963 157# endif
0120be6f
KZ
158#endif
159
160#if !defined(HAVE_FSCONFIG) && defined(SYS_fsconfig)
161static inline int fsconfig(int fd, unsigned int cmd, const char *key,
162 const void *value, int aux)
163{
164 return syscall(SYS_fsconfig, fd, cmd, key, value, aux);
165}
166#endif
167
168#ifndef FSOPEN_CLOEXEC
169# define FSOPEN_CLOEXEC 0x00000001
170#endif
171
172#if !defined(HAVE_FSOPEN) && defined(SYS_fsopen)
173static inline int fsopen(const char *fsname, unsigned int flags)
174{
175 return syscall(SYS_fsopen, fsname, flags);
176}
177#endif
178
179#ifndef FSMOUNT_CLOEXEC
180# define FSMOUNT_CLOEXEC 0x00000001
181#endif
182
183#if !defined(HAVE_FSMOUNT) && defined(SYS_fsmount)
184static inline int fsmount(int fd, unsigned int flags, unsigned int mount_attrs)
185{
186 return syscall(SYS_fsmount, fd, flags, mount_attrs);
187}
188#endif
189
190#ifndef FSPICK_CLOEXEC
191# define FSPICK_CLOEXEC 0x00000001
192#endif
193
194#ifndef FSPICK_SYMLINK_NOFOLLOW
195# define FSPICK_SYMLINK_NOFOLLOW 0x00000002
196#endif
197
198#ifndef FSPICK_NO_AUTOMOUNT
199# define FSPICK_NO_AUTOMOUNT 0x00000004
200#endif
201
202#ifdef FSPICK_EMPTY_PATH
203# define FSPICK_EMPTY_PATH 0x00000008
204#endif
205
206#if !defined(HAVE_FSPICK) && defined(SYS_fspick)
207static inline int fspick(int dfd, const char *pathname, unsigned int flags)
208{
209 return syscall(SYS_fspick, dfd, pathname, flags);
210}
211#endif
212
ded434a6
KZ
213#endif /* HAVE_MOUNTFD_API */
214
215/*
216 * statmount() and listmount()
217 */
218#ifdef HAVE_STATMOUNT_API
219
220#ifndef MNT_ID_REQ_SIZE_VER0
221# define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */
222#endif
223#ifndef MNT_ID_REQ_SIZE_VER1
224# define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */
225#endif
226
227/*
228 * The structs mnt_id_req and statmount may differ between kernel versions, so
229 * we must ensure that the structs contain everything we need. For now (during
230 * development), it seems best to define local copies of the structs to avoid
231 * relying on installed kernel headers and to avoid a storm of #ifdefs.
232 */
233
234/*
235 * listmount() and statmount() request
236 */
237struct ul_mnt_id_req {
238 uint32_t size;
239 uint32_t spare;
240 uint64_t mnt_id;
241 uint64_t param;
242 uint64_t mnt_ns_id;
243};
244
245/*
246 * Please note that due to the variable length of the statmount buffer, the
247 * struct cannot be versioned by size (like struct mnt_id_req).
248 */
249struct ul_statmount {
467b0c15
KZ
250 uint32_t size; /* Total size, including strings */
251 uint32_t mnt_opts; /* [str] Mount options of the mount */
252 uint64_t mask; /* What results were written */
253 uint32_t sb_dev_major; /* Device ID */
ded434a6 254 uint32_t sb_dev_minor;
467b0c15
KZ
255 uint64_t sb_magic; /* ..._SUPER_MAGIC */
256 uint32_t sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */
257 uint32_t fs_type; /* [str] Filesystem type */
258 uint64_t mnt_id; /* Unique ID of mount */
259 uint64_t mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */
260 uint32_t mnt_id_old; /* Reused IDs used in proc/.../mountinfo */
ded434a6 261 uint32_t mnt_parent_id_old;
467b0c15
KZ
262 uint64_t mnt_attr; /* MOUNT_ATTR_... */
263 uint64_t mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */
264 uint64_t mnt_peer_group; /* ID of shared peer group */
265 uint64_t mnt_master; /* Mount receives propagation from this ID */
266 uint64_t propagate_from; /* Propagation from in current namespace */
267 uint32_t mnt_root; /* [str] Root of mount relative to root of fs */
268 uint32_t mnt_point; /* [str] Mountpoint relative to current root */
269 uint64_t mnt_ns_id; /* ID of the mount namespace */
270 uint32_t fs_subtype; /* [str] Subtype of fs_type (if any) */
271 uint32_t sb_source; /* [str] Source string of the mount */
272 uint32_t opt_num; /* Number of fs options */
273 uint32_t opt_array; /* [str] Array of nul terminated fs options */
274 uint32_t opt_sec_num; /* Number of security options */
275 uint32_t opt_sec_array; /* [str] Array of nul terminated security options */
781a960c 276 uint64_t __spare2[46];
467b0c15 277 char str[]; /* Variable size part containing strings */
ded434a6
KZ
278};
279
280/* sb_flags (defined in kernel include/linux/fs.h) */
281#ifndef SB_RDONLY
467b0c15
KZ
282# define SB_RDONLY BIT(0) /* Mount read-only */
283# define SB_NOSUID BIT(1) /* Ignore suid and sgid bits */
284# define SB_NODEV BIT(2) /* Disallow access to device special files */
285# define SB_NOEXEC BIT(3) /* Disallow program execution */
286# define SB_SYNCHRONOUS BIT(4) /* Writes are synced at once */
287# define SB_MANDLOCK BIT(6) /* Allow mandatory locks on an FS */
288# define SB_DIRSYNC BIT(7) /* Directory modifications are synchronous */
289# define SB_NOATIME BIT(10) /* Do not update access times. */
290# define SB_NODIRATIME BIT(11) /* Do not update directory access times */
ded434a6 291# define SB_SILENT BIT(15)
467b0c15
KZ
292# define SB_POSIXACL BIT(16) /* Supports POSIX ACLs */
293# define SB_INLINECRYPT BIT(17) /* Use blk-crypto for encrypted files */
294# define SB_KERNMOUNT BIT(22) /* this is a kern_mount call */
295# define SB_I_VERSION BIT(23) /* Update inode I_version field */
296# define SB_LAZYTIME BIT(25) /* Update the on-disk [acm]times lazily */
ded434a6
KZ
297#endif
298
299/*
300 * @mask bits for statmount(2)
301 */
302#ifndef STATMOUNT_SB_BASIC
467b0c15 303# define STATMOUNT_SB_BASIC 0x00000001U /* Want/got sb_... */
ded434a6
KZ
304#endif
305#ifndef STATMOUNT_MNT_BASIC
467b0c15 306# define STATMOUNT_MNT_BASIC 0x00000002U /* Want/got mnt_... */
ded434a6
KZ
307#endif
308#ifndef STATMOUNT_PROPAGATE_FROM
467b0c15 309# define STATMOUNT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */
ded434a6
KZ
310#endif
311#ifndef STATMOUNT_MNT_ROOT
467b0c15 312# define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */
ded434a6
KZ
313#endif
314#ifndef STATMOUNT_MNT_POINT
467b0c15 315# define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */
ded434a6
KZ
316#endif
317#ifndef STATMOUNT_FS_TYPE
467b0c15 318# define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
ded434a6
KZ
319#endif
320#ifndef STATMOUNT_MNT_NS_ID
467b0c15 321# define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
ded434a6
KZ
322#endif
323#ifndef STATMOUNT_MNT_OPTS
467b0c15 324# define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
ded434a6 325#endif
781a960c 326#ifndef STATMOUNT_FS_SUBTYPE
467b0c15 327# define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */
781a960c
KZ
328#endif
329#ifndef STATMOUNT_SB_SOURCE
467b0c15 330# define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
781a960c
KZ
331#endif
332#ifndef STATMOUNT_OPT_ARRAY
467b0c15 333# define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
781a960c
KZ
334#endif
335#ifndef STATMOUNT_OPT_SEC_ARRAY
467b0c15 336# define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */
781a960c
KZ
337#endif
338
013e0db4 339
ded434a6
KZ
340/*
341 * Special @mnt_id values that can be passed to listmount
342 */
343#ifdef LSMT_ROOT
467b0c15 344# define LSMT_ROOT 0xffffffffffffffff /* root mount */
ded434a6
KZ
345#endif
346
36fed3c7 347#ifndef LISTMOUNT_REVERSE
467b0c15 348# define LISTMOUNT_REVERSE BIT(0) /* List later mounts first */
ded434a6
KZ
349#endif
350
b3bb8291 351/* Don't use this "raw" version. See ul_statmount() below. */
ded434a6 352#if defined(SYS_statmount)
b3bb8291 353static inline int ul_statmount_syscall(uint64_t mnt_id,
ded434a6
KZ
354 uint64_t ns_id,
355 uint64_t mask,
356 struct ul_statmount *buf,
357 size_t bufsize, unsigned int flags)
358{
359 struct ul_mnt_id_req req = {
360 .size = MNT_ID_REQ_SIZE_VER1,
361 .mnt_id = mnt_id,
362 .param = mask,
363 .mnt_ns_id = ns_id
364 };
365
366 return syscall(SYS_statmount, &req, buf, bufsize, flags);
367}
ded434a6 368
b3bb8291 369static inline int has_statmount(void)
ded434a6 370{
b3bb8291 371 errno = 0;
ded434a6 372
b3bb8291
KZ
373 if (ul_statmount_syscall(0, 0, 0, NULL, 0, 0) < 0 && errno == ENOSYS)
374 return 0;
375 return 1;
ded434a6 376}
ded434a6
KZ
377
378/* This is a version of statmount() that reallocates @buf to be large enough to
379 * store data for the requested @id. This function never deallocates; it is the
380 * caller's responsibility.
381 */
b3bb8291 382static inline int ul_statmount(uint64_t id,
ded434a6
KZ
383 uint64_t ns_id,
384 uint64_t mask,
385 struct ul_statmount **buf,
386 size_t *bufsiz,
387 unsigned int flags)
388{
389 size_t sz;
390 int rc = 0;
391
392 if (!buf || !bufsiz)
393 return -EINVAL;
394
395 sz = *bufsiz;
396 if (!sz)
397 sz = 32 * 1024;
398
399 do {
400 if (sz > *bufsiz) {
401 struct ul_statmount *tmp = realloc(*buf, sz);
402 if (!tmp)
403 return -ENOMEM;
404 *buf = tmp;
405 *bufsiz = sz;
406 }
407
408 errno = 0;
b3bb8291 409 rc = ul_statmount_syscall(id, ns_id, mask, *buf, *bufsiz, flags);
ded434a6
KZ
410 if (!rc)
411 break;
412 if (errno != EOVERFLOW)
413 break;
414 if (sz >= SIZE_MAX / 2)
415 break;
416 sz <<= 1;
417 } while (rc);
418
419 return rc;
420}
b3bb8291
KZ
421#endif /* SYS_statmount */
422
423
424#if defined(SYS_listmount)
425static inline ssize_t ul_listmount(uint64_t mnt_id,
426 uint64_t ns_id,
427 uint64_t last_mnt_id,
428 uint64_t list[], size_t num,
429 unsigned int flags)
430{
431 struct ul_mnt_id_req req = {
432 .size = MNT_ID_REQ_SIZE_VER1,
433 .mnt_id = mnt_id,
434 .param = last_mnt_id,
435 .mnt_ns_id = ns_id
436 };
437
438 return syscall(SYS_listmount, &req, list, num, flags);
439}
78ade438
KZ
440
441static inline int has_listmount(void)
442{
443 uint64_t dummy;
444
445 errno = 0;
446
447 if (ul_listmount(LSMT_ROOT, 0, 0, &dummy, 1, LISTMOUNT_REVERSE) != 1)
448 return 0;
449 return 1;
450}
b3bb8291 451#endif
ded434a6
KZ
452
453#endif /* HAVE_STATMOUNT_API */
454
455#endif /* HAVE_LINUX_MOUNT_H */
456
457#endif /* UTIL_LINUX_MOUNT_API_UTILS */